How to get a value back from a multilevel nested callback? [duplicate] - javascript

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 17 days ago.
I am using the mssql npm library which is working, but I am struggling to get the recordset returned from the sub-level callback.
How do I get the recordset back when it's multiple layers of callback?
let storedRecordset = await doQuery();
async function doQuery(){
let recordset;
const ps = new sql.PreparedStatement(/* [pool] */)
ps.input('param', sql.Int)
ps.prepare('select #param as value', err => {
// ... error checks
ps.execute({param: 12345}, (err, result) => {
// ... error checks
recordset = result;
// release the connection after queries are executed
ps.unprepare(err => {
// ... error checks
return recordset;
})
})
})
}
Thanks

let storedRecordset = await doQuery();
function doQuery() {
return new Promise((r) => {
let recordset;
const ps = new sql.PreparedStatement(/* [pool] */);
ps.input("param", sql.Int);
ps.prepare("select #param as value", (err) => {
// ... error checks
ps.execute({ param: 12345 }, (err, result) => {
// ... error checks
recordset = result;
// release the connection after queries are executed
ps.unprepare((err) => {
// ... error checks
r(recordset);
});
});
});
});
}

Related

how do you use stripe.checkout.sessions.listLineItems? [duplicate]

This question already has answers here:
How to "await" for a callback to return?
(5 answers)
Closed 1 year ago.
I'm using stripe and I'm trying to list all items the customer has bought, but logging
those items returns undefined. What did I do wrong? And how does the listLineItems function work?
(The session object is a stripe checkout session object.)
if(event.type === "checkout.session.completed") {
const session = event.data.object;
var items = await stripe.checkout.sessions.listLineItems(
session.id,
function(err, lineItems) {
console.log(err);
}
);
console.log(items);
}
You should wrap listLineItems call in a Promise to be able to await it:
const items = await new Promise((resolve, reject) => {
stripe.checkout.sessions.listLineItems(
session.id,
{ limit: 100 },
(err, lineItems) => {
if(err) {
return reject(err);
}
resolve(lineItems)
}
)
})

How to return new promise object from backend service file to backend controller? [duplicate]

This question already has answers here:
How do I convert an existing callback API to promises?
(24 answers)
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 3 years ago.
I am trying to connect to Recurly API in backend service file, then return as a new promise to backend controller.
For some reason my code does't work.
I keep receiving this error message:
0|account- | TypeError [ERR_INVALID_ARG_TYPE]: The first argument must be one of type string, Buffer, ArrayBuffer, Array, or Array-like Object. Received type undefined
This is my code, the API configuration and other setup works fine. Keep in mind this is part of the project code.
Service.js:
const Recurly = require('recurly-js');
function TeamService({}) {
this.updateBillingInfo = (team_id, body) => {
const recurly = new Recurly(
{
API_KEY: config.recurly.API_KEY,
SUBDOMIAN: config.recurly.SUBDOMIAN,
ENVIRONMENT: config.recurly.ENVIRONMENT,
DEBUG: config.recurly.DEBUG,
API_VERSION: config.recurly.API_VERSION
}
);
return new Promise((resolve, reject) => {
let res;
let err;
recurly.billingInfo.update(team_id, { token_id: body.id }, function (errResponse, response) {
if (errResponse) {
err = errResponse.data.error;
}
if(response){
res = response;
}
});
resolve(res);
reject(err);
});
};
}
}
Controller.js:
function Controller({ teamService, httpStatus, }) {
this.updateBillingInfo = (req, res) => {
const {
team_id,
body
} = req;
teamService.updateBillingInfo(team_id, body).then(function(result){
console.log(result);
return httpStatus.twoHundredSuccess(res, {result});
}).catch(function(err){
console.log(err);
httpStatus.fiveHundredError(res, err);
});
}
}
I expect that the function in service works get information from API. return as a new promise to controller file. But it is not working in service.js. I am not very good with promise. Please let me know which part I did wrong.
Your resolve and reject should be inside the callback of async function:
recurly.billingInfo.update(team_id, { token_id: body.id }, function(
errResponse,
response
) {
if (errResponse) {
reject(errResponse.data.error);
}else{
resolve(response);
}
});

How do I properly get data from an asynchronous callback method with Node/JS? [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
Really sorry if this has been asked a hundred times, but I haven't been able to adapt any previous SO solutions I found to my problem. A lot of them were Ajax specific.
I'm new to asynchronous callbacks with Node, and as such I'm having an issue with properly 'returning' data from an asynchronous callback. In my example, I'm trying to return CharList. The SQL queries and the data are all valid, so those aren't too important.
I've tried simply returning the values, which I quickly learned is impossible and defeats the purpose of asynchronous callbacks.
EDIT: I've also tried defining CharList outside of the function and then assigning the values through the function, but logging CharList after the function has finished prints an empty array.
// index.js
const sql = require('./sql')
const query = require('./queries');
function AllCharsToArray() {
query.character.GetAllChars(function(result) {
let CharList = [];
for (var i in result) {
CharList.push(result[i]._Name)
}
})
}
/*
{
"characters":
[
{"_Name":"Charname 1"},
{"_Name":"Charname 2"},
{"_Name":"Charname 3"}
]
}
*/
// queries.js
const mysql = require('mysql');
const sql = require('./sql')
function GetAllChars(callback) {
sql.conn.query(`SELECT _Name FROM characters;`, function(error, results, fields) {
return callback(results); // returns RowDataPacket
})
}
exports.character = {
GetAllChars: GetAllChars,
}
Ultimately, I'm trying to get CharList to be available outside of AllCharsToArray so I can export them to an express.js route.
Suggested callback function contains error message, like
// queries.js
const mysql = require('mysql');
const sql = require('./sql')
function GetAllChars(callback) {
sql.conn.query(`SELECT _Name FROM characters;`, function(error, results, fields) {
// change as
if(error) {
return callback(error)
}
callback(null,results); // returns RowDataPacket
})
}
exports.character = {
GetAllChars: GetAllChars,
}
On index.js
...
function(req,res){
query.character.GetAllChars(function(err,data){
// check error info
if(err){
// console.debug(err)
return res.send(err.message)
}
res.json(data)
})
}
...
Placing the CharList outside the AllCharsToArray()
// index.js
const sql = require('./sql')
const query = require('./queries');
query.character.GetAllChars(function(result) {
const CharList = [];
for (var i in result) {
CharList.push(result[i]._Name);
}
// launch the route after GetAllChars is done
expressApp.get('getCharList', (req, res) => {
res.json(CharList);
});
});

Combining async requests into a single GET API [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 3 years ago.
I am trying to call a GET API under three different configurations for region parameter, and combine the results into a single result object which I want the API to return as a JSON.
Here is my approach, which uses an array of Promises.
app.get("/api/v2/leagues/games", (req, res) => {
const regions = ['uk', 'us', 'au'];
let result = {};
let promiseArray = regions.map(region => {
return new Promise((resolve, reject) => {
const uri = `https://api.the-odds-api.com/v3/odds/?apiKey=${functions.config().theoddsapi.key}&sport=${req.query.league}&region=${region}&mkt=${req.query.mkt}`;
console.log(uri);
request.get(uri, (error, response, body) => {
if (body) {
result[region] = JSON.parse(body).data;
resolve(body);
}
else {
console.error("error:", error);
console.log("statusCode:", response && response.statusCode);
reject(error);
}
});
});
});
Promise.all(promiseArray).then(() => {
return res.json(result)
}).catch(() => response.errorCode);
});
});
The approach you are using it correct, however you have made a little mistake.
Though I have not tested it but the following code should do what you want it to do.
app.get("/api/v1/leagues/games", (req, res) => {
const promiseRequest = (sport, region, mkt) => {
return new Promise(resolve => {
const theOddsApiUrl = `https://api.the-odds-api.com/v3/odds/?apiKey=${functions.config().theoddsapi.key}&sport=${sport}&region=${region}&mkt=${mkt}`;
request.get(theOddsApiUrl, (error, response, body) => {
if (body) {
resolve(body)
}
});
})
}
var sport = req.query.sport;
var mkt = req.query.mkt;
let allRegionsOdds = {};
Promise.all([
promiseRequest(sport, 'uk', mkt),
promiseRequest(sport, 'us', mkt),
promiseRequest(sport, 'au', mkt)
]).then(body => {
var response = allRegionsOdds[region] = body; // you can deide if this assignment is necessary or not for you
res.json(response); // You want to return the response for the main Get after all the promises have been fulfilled.
}).catch(); // You can handle special cases in the catch, forexample when some promises fail.
//if you return the json at the end of function, your Promise.all hasn't gotten the time to be complete yet
//and hence the variable response is still empty
//res.json(response);
});

Wait for Inner Function to Complete Before Returning Value [duplicate]

This question already has answers here:
How do I return the response from an asynchronous call?
(41 answers)
Closed 5 years ago.
I have a function that makes a database query, then needs to return the result.
The query is to a mysql database, using Node.js, the result is then returned to an Inquirer (NPM module) prompt.
If this was a front end issue, I would use the built in promises of jquery: (example). $.ajax.done(). However the mysql NPM package doesn't have built in promises for the query() method.
// OPTION 1, wait for query to complete before returning choicesArray (this example returns an empty array)
choices() {
let choicesArray = [];
connection.query(`SELECT * FROM products`, (err, res)=>{
for (item of res) {
choicesArray.push(`${item.product} | ${item.price}`);
};
});
// wait here for query to complete
return choicesArray;
}
// OPTION 2, change the syntax to take advantage of the query callback, something more like below (this example does not return the choicesArray all the way to the enclosing function)
choices() {
connection.query(`SELECT * FROM products`, (err, res)=>{
let choicesArray = [];
for (item of res) {
choicesArray.push(`${item.product} | ${item.price}`);
};
return choicesArray;
});
} // (node:3877) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: You must provide a `choices` parameter
You can't return a value from an async function like that. The function returns before your async values are ready. You either need to use a callback like:
function choices(cb) {
let choicesArray = [];
connection.query(`SELECT * FROM products`, (err, res)=>{
if (err) {
cb(err)
return
}
for (item of res) {
choicesArray.push(`${item.product} | ${item.price}`);
};
});
// wait here for query to complete
cb(null, choicesArray);
}
choices((err, value) =>{
if (err) {
// handle error
}
// use value here
})
Or return a promise like:
function choices() {
return new Promise((resolve, reject) => {
connection.query(`SELECT * FROM products`, (err, res)=>{
if (err) return reject(err)
let choicesArray = [];
for (item of res) {
choicesArray.push(`${item.product} | ${item.price}`);
}
resolve(choicesArray)
});
})
}
choices()
.then(value => {
// use value here
})
.catch(err =>{
// handle error
})

Categories

Resources