How to make this nodejs lambda wait until the job is done? - javascript

I'm a newbie in nodejs.
I have an AWS lambda that reads a queue and delete messages after processing them:
const AWS = require('aws-sdk');
AWS.config.logger = console;
const sqs = new AWS.SQS({apiVersion: '2012-11-05'});
const redriveQueueUrl = 'https://myqueue";
async function deleteMessage (messageToDelete) {
let params = {
QueueUrl: redriveQueueUrl,
ReceiptHandle: messageToDelete.ReceiptHandle
};
sqs.deleteMessage(params, function (err, data) {
if (err) console.log(err, err.stack);
else console.log(data);
});
}
exports.handler = async (event) => {
var params = {
QueueUrl: redriveQueueUrl,
MaxNumberOfMessages: '2',
};
let sqsResponse = await sqs.receiveMessage(params).promise();
let messages = sqsResponse.Messages
for (let index in messages) {
// do something here later.
await deleteMessage(messages[index]);
};
const response = {
statusCode: 200,
body: JSON.stringify('End of Lambda!'),
};
return response;
};
This code correctly reads a given queue but does not delete any message.
How can fix this problem?

sqs.deleteMessage needs to return a promise. Otherwise calling await sqs.deleteMessage() will return immediately.
Try this:
async function deleteMessage (messageToDelete) {
let params = {
QueueUrl: redriveQueueUrl,
ReceiptHandle: messageToDelete.ReceiptHandle
};
return new Promise((resolve, reject)=>{
sqs.deleteMessage(params, function (err, data) {
if (err) return reject(err);
else return resolve(data);
});
})
}

Related

How to return data from RabbitMQ consume function in nodejs?

I have consume function like this.
In this case when i put console.log() in consume callback function, i see messages coming from queue.
Function 1
async function consumeData() {
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = message.content.toString();
console.log(consumedData);
channel.ack(message);
});
} catch (error) {
console.log("Error", error);
}
}
But i dont wanna log this data. I wanna return and use it like this.
Function 2
async function consumeData() {
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = message.content.toString();
console.log(consumedData);
channel.ack(message);
});
return consumedData;
} catch (error) {
console.log("Error", error);
}
}
When i run function 2 i cant return any data. How can i return data from this consume function?
return it after trycatch
async function consumeData() {
var consumedData = {};
try {
const connection = await amqp.connect("amqp://localhost:5672");
const channel = await connection.createChannel();
await channel.assertQueue(queueName);
let consumedData;
channel.consume(queueName, (message) => {
consumedData = JSON.parse(message.content.toString());
channel.ack(message);
});
} catch (error) {
console.log("Error", error);
}
return consumedData;
}
and call the function using await
const data = await consumeData();

Second function not called asynchronously in nodejs

I am trying to call some function using a single express router , I want to call them in order, meaning that I don't want getLaps() function to execute before get streams function has done all the work , so I tried to use some solutions I found on the internet but it didn't work, the second function doesn't execute. Please help.
Here is my code :
router.get("/", async (req, res,done) => {
res.status(201).send('created user')
return getLaps(function () {
getStreams(function () {
});
});
// await getStreams();
// await getLaps();
// console.log("hey")
});
Here is the get laps function :
function getLaps(req) {
const access_token = '75f2d92fdc445033312854d775e039b6c5bf04e7';
//for test 3756582581,
const idL = [5567017025, 5566531480];
const stravaClient = StravaClientService.getClient(access_token);
const activityService = StravaActivityService(stravaClient);
var params = {
TableName: "run-id",
Key: {
"id": "15428785",
}
};
console.log("cool laps")
docClient.get(params, async function (err, data) {
if (err) {
console.log("Error", err);
} else {
}
idL.map((id, index) => setTimeout(() => activityService.listLaps(id), (5 + index) * 60)
)
//data.Item.json
});
}
and the streams function :
function getStreams(req) {
const idS = [
5567017025, 5566531480
];
const stravaClient = StravaClientService.getClient(access_token);
const activityService = StravaActivityService(stravaClient);
var params = {
TableName: "run-id",
Key: {
"id": "15428785",
}
};
console.log("cool streams")
docClient.get(params, async function (err, data) {
if (err) {
console.log("Error", err);
} else {
idS.map((id, index) => setTimeout(() => activityService.streamActivity(id), (5 + index) * 60))
console.log("got the streams")
}
});
}
in your getStream and getLaps function return promises instead of other object/Stuff like
async function getStream(){
return new Promise(async (resolve, reject){
//Do something
//where you want to return something just call resolve function like
resolve()
//if you want some output of getStream() just pass it to resolve function
//const result = 'I'm result'
resolve(result)
})
}
do same thing with the laps function and in your router call them with await keyword

readFileSync returns undefined when trying to read data from files

I created multiples functions under a directory called data and fill them with some random data returned by a function called generatedRandomData.
To create multiple files I wrote these functions:
const createFile = (fileName, data) => {
if (fs.existsSync(fileName)) throw new Error('Filename already exists');
fs.writeFile(fileName, data, {
encoding: 'utf8',
flag: 'w',
}, (error) => {
if (error) return error;
console.log('File created successfully');
return null;
});
};
const createFiles = (dirPath, sizeList) => {
if (sizeList && !sizeList.length) throw new Error('The list of size should not be empty');
const fileCreationPromises = sizeList.map(async (size) => {
const data = generateRandomData(size);
const fileName = resolve(dirPath, `./data_${size}.txt`);
await createFile(fileName, data);
});
return Promise.all(fileCreationPromises);
};
Then I call the function generateData in order to generate random data and call the functions described above then create the files:
const generateData = async (dirPath, sizeList) => {
if (!dirPath) throw new Error('No directory path was provied');
if (!sizeList || (sizeList && !sizeList.length)) throw new Error('Size list should not be empty');
await createFiles(dirPath, sizeList);
};
I call another function called execute which reads data from those file in order to continue the treatment:
const execute = async (func, dirPath, label) => {
const files = fs.readdirSync(dirPath);
const result = [];
if (files && files.length) {
for (const file of files) {
const filename = resolve(dirPath, `./${file}`);
const parsedData = readDataFromFile(filename);
const data = parsedData.split(',').map((d) => Number(d));
const { length } = data;
result.push({
label: length,
value: getExecutionTime(func, data),
});
}
}
await createFile(resolve(dirPath, `./${label}`), result);
};
Finally, I call the function initialize:
const { resolve } = require('path');
const fs = require('fs');
const { generateData, sizeList, execute } = require('../utils/helpers');
const { underscorePartial } = require('../main/partial');
const dirPath = resolve(__dirname, '../data');
const initialize = () => {
if (!fs.existsSync(dirPath)) {
fs.mkdir(dirPath, async (error) => {
if (error) throw error;
await generateData(dirPath, sizeList);
await execute(underscorePartial, dirPath, 'uExecutionTime.txt');
});
}
};
try {
initialize();
} catch (error) {
console.log(error);
}
However I realized that uExecutionTime.txt to be created in the final step contains undefined due to the function readDataFromFile which returns undefined.
I guess the readDataFromFile starts reading from files before the creation of data finished.Any suggestions to fix my code or are there anything missed or wrong in the code?
The problem is your createFile function. You care awaiting it while it doesn't return promise. It is a callback style. It should be wrapped in promise.
const createFile = (fileName, data) => {
if (fs.existsSync(fileName)) throw new Error('Filename already exists');
return new Promise((resolve, reject) => {
fs.writeFile(fileName, data, {
encoding: 'utf8',
flag: 'w',
}, (error) => {
if (error) reject(error);
console.log('File created successfully');
resolve(null);
});
});
};
Hope this resolves the issue.

Promise returns wrong value

In my code I try to assign a value to json variable to return it after (because I can't return it from the anon. function).
As my function is async, because it sends requests (maybe someone knows how to make it sync? I didn't plan to make it asynchronous), I've added await before the request (https.get).
I've been trying to get value from the Promise, but it's always undefined, even though I've awaited the async function.
Here's a code:
async function get_users() {
const https = require('https');
var token = '...';
var json = undefined;
await https.get('...', (resp) => {
let data = '';
resp.on('data', (chunk) => {
data += chunk;
});
resp.on('end', () => {
json = JSON.parse(data)['response']['items'];
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
return json;
}
get_users().then(function(result) {
console.log(result);
});
Return a Promise and resolve it, when the end event is called, otherwise reject it in case of an error occurred:
async function get_users() {
const https = require('https');
const token = '...';
return new Promise((resolve, reject) => {
https.get('...', resp => {
let data = '';
resp.on('data', chunk => {
data += chunk;
});
resp.on('end', () => {
let json;
try {
json = JSON.parse(data)['response']['items'];
} catch (e) {
reject(e);
};
resolve(json);
});
}).on("error", err => reject(err));
});
}
get_users().then(result => console.log(result));
Please refer my below code.I had issues with getting responses from Promises too.But i finally got it to work.Here's the code:
var output;
var rp = require('request-promise-native');
var myJSONObject = {
"inputs": [{
"name": "<name>",
"value": < value >
}]
};
var orchName = 'TEST05';
postData = JSON.stringify(myJSONObject);
return networkCall(postData, orchName).then((response) => {
console.log('response is' + response)
}).catch((response) => {
console.log(`ERROR: ` + response);
});
function networkCall(postData, orchName) {
return new Promise((resolve, reject) => {
var options = {
method: 'post',
uri: '<URL>',
body: postData,
auth: {
'user': 'usr',
'pass': 'pwd'
},
json: true
};
return rp(options)
.then(body => {
var response = body;
resolve(response);
})
.catch(err => {
console.log('FAILED' + err);
reject(err);
});
});
}
This way your code can run in Synchronous Flow.If the return value is undefined,then,what might have probably happened is that the calling function would have finished executing even before the called function returns its response.But the above approach would work just fine.

REST API calls using async await

Here's my code snippet
var clients = require('restify-clients');
async function callApi(val){
const client = clients.createJsonClient({ url: apiUrl });
await client.get('/my/url', (err, req, res, obj) => {
if (err) {
return err;
} else {
return obj;
}
});
}
I've tried a few ways of calling it, but they all aren't working
First way:
var results = await callApi(val);
Second way:
var results = callApi(val).then(data => {
console.log(data);
})
client.get doesn't return a promise, you can't use await on a function which doesn't return a promise (honestly you can, but it doesn't make sense). The correct solution here is to promisify client.get and return a promise:
function callApi(val) {
const client = clients.createJsonClient({ url: apiUrl });
return new Promise((resolve, reject) => {
client.get('/my/url', (err, req, res, obj) => {
if (err) {
reject(err);
} else {
resolve(obj);
}
});
});
}
// Usage
let results = await callApi(val);
Try to remove await from results
var results = callApi(val);

Categories