How to extract the value of a variable outside Nodejs callback function - node.js

I am unable to get the value of the response outside the callback code. It returns undefined outside whereas in the callback it is giving proper result.
function doCall(urlString, callback) {
request.get(
urlString,
null,
null,
(err, data, result) => {
var statusCode = result.statusCode;
return callback(data);
}
);
}
const apiResponse = doCall(urlString, function(response) {
console.log('***************************' + response); //Prints correct result
return JSON.parse(response);
});
console.log('+++++++++++++++++++++++++' + apiResponse); //Prints undefined

function doCall(urlString) {
return new Promise((resolve, reject) => {
request.get(
urlString,
null,
null,
(err, data, result) => {
if (error) reject(error);
var statusCode = result.statusCode;
resolve(data);
});
});
}
async function myBackEndLogic() {
try {
const result = await doCall(urlString);
console.log(result);
//return JSON.parse(result) if you want
} catch (error) {
console.error('ERROR:');
console.error(error);
}
}
myBackEndLogic();
Read this for more explanations

If you want synchronous looking code, wrap everything in an async function:
(async (){
async function doCall(urlString, callback) {
return await request.get(urlString, null, null); // or store in a variable and return modified response
}
const apiResponse= await doCall(urlString, (response) => {
console.log('response', response);
return JSON.parse(response);
});
console.log('apiResponse', apiResponse);
})()

Related

nodejs: Not able to read response from callback function in the main function

Noob in nodejs here and still trying to learn how nodejs works. Could you please let me know how can I pass the callback response from "getDatafromCosmosDB" function into a variable in the main function and print those values.
When I try to assign getDatafromCosmosDB to a variable "respdata" and try to print it, it is not working.
async function main(params, callback) {
const logger = Core.Logger('main2', { level: params.LOG_LEVEL || 'info' })
try {
logger.info('main action')
const respdata = getDatafromCosmosDB(function(response){
console.debug(response)
return response
});
console.debug(respdata)
} catch (e) {
console.debug(e)
}
}
exports.main = main
async function getDatafromCosmosDB(callback){
var query = new azure.TableQuery()
.top(5)
tableService.queryEntities('myCosmosTable', query, null, function (error, result, response) {
if (!error) {
console.log('success')
return callback(result.entries)
}
});
}
Try something like this,
import {
createTableService,
services,
ServiceResponse,
TableQuery
} from 'azure-storage';
getDatafromCosmosDB(): Promise<ServiceResponse> {
return new Promise(async (resolve, reject) => {
this.tableService.queryEntities(
this.tableName,
query,
null,
(error, _, response) => {
if (!error) {
resolve(response);
} else {
reject(error);
}
}
);
});
}
and invoke like,
this.getDatafromCosmosDB().then(data => {
console.log(data);
}

How can I make code wait for the return of an API call - Node.js

I am trying to write a function which makes an API call and wait until the API has returned a value, how do I improve my code to do this. At the moment it just returns Promise-pending.
async function getData(options){
const result = new Promise((resolve, reject) => {
request(options, function(error, response) {
if (error) return reject(error);
return resolve(JSON.parse(response.body));
});
});
var fromapi = await result;
return fromapi;
};
Try this
const request = require('request')
function makeRequest(uri, options) {
return new Promise((resolve, reject) => {
return request(uri, options, function (error, response) {
if (error) reject(error);
resolve(response.body);
});
});
}
async function getData(options) {
const result = await makeRequest('https://google.com', options)
console.log(result)
}
getData().then(() => {
}).catch((e) => {
console.log(e)
})

how to return results to postman using nodejs.i couldn't send result

App.js
app.get('/getCus', function (req, res) {
var id= req.query;
cus_controller.getCus(id,function(response) {
res.json(response);
});
});
cus_controller.js:
module.exports ={
getCus: function (id, callback) {
getCus = function () {
getOneCus(id).then(result => {
callback(result);
}).catch(err => {
callback(err)
})
}
process.nextTick(getCus);
},
}
async function getOneCus(id) {
auth.authClient(function (err, client) {
if (client) {
function callback(error, response, body) {
if (!error && response.statusCode == 200) {
console.log(body);
}
}
getCus(id,client, callback);
}
else {
console.error(err);
}
})
}
var getCus = (id, client, callback) => {
client
.invokeApi(null, `/cus/${id}`, 'GET')
.then(function (result) {
console.log(result.data);
return result.data
})
.catch(function (result) {
if (result.response) {
console.dir({
status: result.response.status,
statusText: result.response.statusText,
data: result.response.data
});
} else {
console.log(result.message);
}
});
}
in getCus method getting a response in the console. however, couldn't get a response in postman.it shows 200 status code but didn't get a response. Someone help me, please. I could not find any solution for this.i tried many methods like return data and res.send(data).
You're passing a callback function to getCus, but you never use it. It looks like you meant call it instead of return the result:
client
.invokeApi(null, `/cus/${id}`, 'GET')
.then(function (result) {
console.log(result.data);
callback(result.data); // <-- here
})
Alternatively, if you return the result as you currently do, then you wouldn't pass a callback to getCus but would instead use a .then() structure:
cus_controller.getCus(id).then(function(response) {
res.json(response);
});
But be sure to also return the top-level Promise by returning the call to client.invokeApi:
return client // <-- here
.invokeApi(null, `/cus/${id}`, 'GET')
.then(function (result) {
console.log(result.data);
return result.data
})

promise all not working as expected while working with list

I want the callback to return the response when promise all finishes. I am getting the response before promise all. Batch List is empty in response, as it is returned before promise all.
getByReferenceID(object, mode, limit, lastEvaluatedKey, callback){
var results = {};
var requestList = [];
var batchList = [];
var response = {};
new Promise((resolve, reject) => {
this.getRequestList(object, limit, lastEvaluatedKey,function (err, result) {
console.log(result);
results = result;
if(err) {
reject();
} else {
resolve();
}
});
}).then(async () =>
{
requestList = requestList.concat(results.items);
const runAsyncFunctions = async () => {
var promises = [];
requestList.map(async request => {
var promise = await this.getBatchList(request.requestID.S, mode, null, null, function(err, result) {
batchList = batchList.concat(result.items);
});
promises.concat(promise);
});
await Promise.all(
promises
).then(()=>{
response = {
"requests": requestList,
"batches": batchList,
"lastEvaluatedKey": results.LastEvaluatedKey
};
callback("", response);
}).catch((error) => {
console.log(error);
});
};
await runAsyncFunctions();
}).catch((error) => {
callback(error, response);
});
}
promises is not an array of promises.
The line
var promise = await this.getBatchList(request.requestID.S, mode, null, null, function(err, result) {
batchList = batchList.concat(result.items);
});
is executed later then
callback("", response)
I guess you want to do something like this
var promises = [];
for (const request of requestList) {
const promise = this.getBatchList(request.requestID.S, mode, null, null, function (err, result) {
batchList = batchList.concat(result.items);
});
promises.push(promise);
}
await Promise.all(
...
The correct way of doing it is:
getByReferenceID(object, mode, limit, lastEvaluatedKey, callback){
var results = {};
var requestList = [];
var batchList = [];
var response = {};
new Promise((resolve, reject) => {
this.getRequestList(object, limit, lastEvaluatedKey,function (err, result) {
console.log(result);
results = result;
if(err){
reject(err);
}
else{
resolve();
}
});
return results;
}).then(() =>
{
requestList = requestList.concat(results.items);
var iteration =0;
new Promise((resolve, reject) => {
for (let request of requestList) {
console.log(request.requestID.S);
this.getBatchList(request.requestID.S, mode, null, null, function (err, result) {
iteration++;
batchList = batchList.concat(result.items);
if(iteration === requestList.length)
{
resolve();
}
if(err)
{
reject();
}
});
}
}).then(()=>{
response = {
"requests": requestList,
"batches": batchList,
"lastEvaluatedKey": results.LastEvaluatedKey,
};
callback("", response);
}).catch((error) => {
callback(error, response);
});
}).catch((error) => {
callback(error, response);
});
}

How to chain promise in array

I need help with ES6 Promises chaining in array processing.
How to process/define each item of array which goes into Promise.all method, when there is other async method inside resolve?
Here is simplified example:
function getData(data, callback) {
let groupPromises = data.map(row => {
var coordinates = getCoordinates(row);
return Promise.resolve({
"place": getPlaces(coordinates), //how to invoke this method
"data": row
};
});
Promise.all(groupPromises)
.then(groups => callback(groups))
.catch(err => console.log(err));
}
}
function getPlaces(coordinates) {
return new Promise(function(resolve, reject) {
if(coordinates == null) {
reject();
}
parameters = {
location: [coordinates.latitude, coordinates.longitude],
rankby: "distance",
};
googlePlaces.searchPlace(parameters, function (error, response) {
if (error) {
reject(error);
};
resolve(response);
});
}
}
You can do it like this where you add a .then() handler to your first promise that gets the place and then when that's available returns the object you want. The resolved results of your Promise.all() will then be the array of objects you want:
function getData(data, callback) {
let groupPromises = data.map(row => {
var coordinates = getCoordinates(row);
// add .then() handler here to convert the place result
// into the object you want it in
return getPlaces(coordinates).then(place => {
return {place: place, data: row};
});
});
return Promise.all(groupPromises)
.then(groups => callback(groups))
.catch(err => {
console.log(err);
throw err;
});
}
}
function getPlaces(coordinates) {
return new Promise(function(resolve, reject) {
if(coordinates == null) {
reject();
}
parameters = {
location: [coordinates.latitude, coordinates.longitude],
rankby: "distance",
};
googlePlaces.searchPlace(parameters, function (error, response) {
if (error) {
reject(error);
};
resolve(response);
});
}
}
FYI, since you're converting over to promises, why not just return the promise from getData() and not use a callback there at all? Your current code has no way of communicating back an error from getData() which is something that comes largely for free with promises.
In fact with pure promises, getData() could be simplified to this:
function getData(data, callback) {
return Promise.all(data.map(row => {
return getPlaces(getCoordinates(row)).then(function(place) {
return {place: place, data: row};
});
}));
}

Resources