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

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)
}
)
})

Related

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

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);
});
});
});
});
}

array.push method not working for my node.js application [duplicate]

This question already has answers here:
How to return many Promises and wait for them all before doing other stuff
(6 answers)
Closed 11 months ago.
router.get("/timeline/:userId", async (req, res) => {
try {
//creating friend posts object
const friendPosts = await Promise.all(
currentUser.followings.map((friendId) => {
return Post.find({ userId: friendId });
})
);
var newFriendPosts = [];
friendPosts.map(async (friend) => {
friend.map(async (post) => {
const { profilePicture, username } = await User.findById(post.userId);
const newFriendPostsObject = {
...post.toObject(),
profilePicture,
username,
};
console.log(newFriendPostsObject);
newFriendPosts.push(newFriendPostsObject);
});
});
console.log(newFriendPosts);
// console.log(newUserPosts);
res.status(200).json(newUserPosts.concat(...newFriendPosts));
} catch (err) {
res.status(500).json(err);
}
});
So the object value is coming correct in console.log(newFriendPostsObject) but when I push that in the array newFriendPosts = []; it shows empty array in console.log(newFriendPosts);
Below is where I am getting user details from DB (DB is in MongoDB):-
const { profilePicture, username } = await User.findById(post.userId);
.map() is NOT async aware. So, it just marches on and returns an array of promises. Meanwhile, your code never waits for those promises so you're trying to use newFriendPosts BEFORE any of your .push() operations have run. .push() is working just fine - you're just trying to use the array before anything has actually gotten around to calling .push(). If you add appropriate console.log() statements, you will see that the newFriendPosts.push(...) occurs after your console.log(newFriendPosts);.
The simplest fix is to change both .map() statements to a regular for loop because a for loop IS async aware and will pause the loop for the await.
router.get("/timeline/:userId", async (req, res) => {
try {
//creating friend posts object
const friendPosts = await Promise.all(
currentUser.followings.map((friendId) => {
return Post.find({ userId: friendId });
})
);
const newFriendPosts = [];
for (let friend of friendPosts) {
for (let post of friend) {
const { profilePicture, username } = await User.findById(post.userId);
const newFriendPostsObject = {
...post.toObject(),
profilePicture,
username,
};
newFriendPosts.push(newFriendPostsObject);
}
}
console.log(newFriendPosts);
res.status(200).json(newUserPosts.concat(...newFriendPosts));
} catch (err) {
res.status(500).json(err);
}
});
One mystery in this code is that newUserPosts does not appear to be defined anywhere.

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);
}
});

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);
});

Handling Promises: How to return a list having promises from a for loop? [duplicate]

This question already has answers here:
Using async/await with a forEach loop
(33 answers)
Closed 3 years ago.
I m trying to push all the returned promises from AWS-Cogntio into a list inside a for loop. I want to return the same list as the final result.
So basically, I m trying to upload a list of users to AWS-Cognito, and i want to return every user's response from Cognito, in a list.
This is the code I have:
let list = [];
body.forEach(async(userItem) => {
await this.userService.uploadUser(userItem) //uploading every user to AWS
.then((user) => { //'user' is the promise returned from AWS
list.push(user);
console.log("list::::", list);
});
})
This is what i tried to do: But the list contains only one value and not the list of values.
return new Promise((resolve) => {
body.forEach(async(userItem) => {
await this.userService.uploadUser(userItem) //uploading every userItem to AWS
.then((user) => { //'user' is the promise returned from AWS
list.push(user);
console.log("list::::", list);
});
})
}).then((data) => {
return res.send(list); //same list of promises
})
This is the output i get, when i m trying to upload for multiple users:
[
{
"message": "An account with the given email already exists.",
"code": "UsernameExistsException",
"time": "2019-05-06T07:15:28.113Z",
"statusCode": 400,
"retryable": false,
"retryDelay": 57.99626693113027
}
]
EDIT :
From the answers given below, this works: Using map instead of for loop returns the same length of list having promises.
try {
let promises = body.map(async(userItem) => {
let user = await this.userService.uploadUser(userItem);
return await new Promise((resolve) => {
resolve(user);
})
});
let data = await Promise.all(promises);
res.send(data);
} catch (error) {
throw error;
}
}
This gives me result list of all the user responses. Thanks!
Unfortunately forEach isn't async/await aware. So try instead with map to return the desired promise lists.
Refer to this for more info on async/await in loops.
I don't know if I understood this correctly but this is what I would do:
const list = body.map(async (userItem) => {
await this.userService.uploadUser(userItem))
});
Promise.all(list).then(() => console.log('worked')).catch(() => console.log('it didnt work'));;
Hope this helps!
return Promise.all(body.map(userItem => this.userService.uploadUser(userItem))
.then((list) => {
res.send(list);
})

Categories

Resources