I'm not sure how to ask this question, but I have a set of promises that all need to be resolved as they are data api requests, but one of the three depends on the other and I'm not sure how to resolve.
The code in question looks like this:
let dependent;
let subscriptions = getSubscriptions() //data fetch
.then((subscriptions) => {
let fieldList = subscriptions.reduce((subscription) => {
if(subscription.Threshold) {
return subscription.Threshold.Field;
}
return null;
});
dependent = getUpdatedInfo(request, body, fieldList); //Data fetch promise
return subscriptions;
});
let userInfo = getUserInformation(); //Data fetch
Promise.all([subscriptions, userInfo, dependent]).then(function(values) {
console.log({ promiseAll: values }); //Dependent is always undefined
processSubscriptions(result, body, userInfo, subscriptions, dependent);
});
I have tried this code a few different ways based on the last 4 hours of googling, but haven't quite figured out what I'm doing wrong here.
You can do this with raw Promises, but it's kinda ugly. Much neater with async/await:
async function whatever() {
const subs = await getSubscriptions();
const fieldList = subs.reduce((subscription) => {
if(subscription.Threshold) {
return subscription.Threshold.Field;
}
return null;
});
const dependent = await getUpdatedInfo(request, body, fieldList);
const userInfo = await getUserInfo();
return processSubscriptions(result, body, userInfo, subscriptions, dependent);
}
NodeJS in non-blocking. All lines are executed synchronously, and dependent
is surely undefined in Promise.all
call because it was set to undefined
in line let dependent;
.then
callback is executed asynchronously, eg after all synchronous code.
If you want to use dependent
which is resolved in then
then you have to chain then
calls.
I would refactor with async/await. To achieve the parallelization you are looking for we create two promises for (userInfo and dependent) and then use promise.All to await their resolution. promise.All returns an array of the result of all the promises.
Make sure to use a try, catch
async function processSubscriptionsHandler(request, body) {
try {
let userInfoPromise = getUserInformation(); // async function returning a promise
let subscriptions = await getSubscriptions()
let fieldList = getFieldList(subscriptions)
let dependentPromise = getUpdatedInfo(request, body, fieldList) // async function returning a promise
let [userInfo, dependent] = await Promise.all([userInfoPromise, dependentPromise]) // await both promises to resolve and map resulting array to variables
processSubscriptions(result,
body,
userInfo,
subscriptions,
dependent);
} catch (e) {
console.error(e)
}
}
function getFieldList(subscriptions) {
subscriptions.reduce((subscription) => {
if (subscription.Threshold) {
return subscription.Threshold.Field;
}
return null;
});
}
I've tried to rejig your logic into promises -- one of the tools you can use for a chain of dependent promises is to declare your variables before the promise, and then set them in the .then
-- that way the variable is available for all closures in the code block:
let subscriptions;
let updatedInfo;
let subscriptionsPromise = getSubscriptions() //data fetch
.then((subscriptionsResults) => {
let fieldList = subscriptionsResults.reduce((subscription) => {
if(subscription.Threshold) {
return subscription.Threshold.Field;
}
return null;
});
subscriptions = subscriptionsResults
return getUpdatedInfo(request, body, fieldList); //Data fetch promise
})
.then(updatedInfoResult => {
updatedInfo = updatedInfoResult;
});
let userInfoPromise = getUserInformation(); //Data fetch
Promise.all([subscriptionsPromise, userInfoPromise]).then(function(values) {
// at this point, subscriptions should have a value,
// and so should updatedInfo,
// and values[1] should be the result from userInfoPromise
});
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.