How to Access Previous Promise Results in a .Then() Chain

How do I access previous promise results in a .then() chain?

ECMAScript Harmony

Of course, this problem was recognized by the language designers as well. They did a lot of work and the async functions proposal finally made it into

ECMAScript 8

You don't need a single then invocation or callback function anymore, as in an asynchronous function (that returns a promise when being called) you can simply wait for promises to resolve directly. It also features arbitrary control structures like conditions, loops and try-catch-clauses, but for the sake of convenience we don't need them here:

async function getExample() {
var resultA = await promiseA(…);
// some processing
var resultB = await promiseB(…);
// more processing
return // something using both resultA and resultB
}

ECMAScript 6

While we were waiting for ES8, we already did use a very similar kind of syntax. ES6 came with generator functions, which allow breaking the execution apart in pieces at arbitrarily placed yield keywords. Those slices can be run after each other, independently, even asynchronously - and that's just what we do when we want to wait for a promise resolution before running the next step.

There are dedicated libraries (like co or task.js), but also many promise libraries have helper functions (Q, Bluebird, when, …) that do this async step-by-step execution for you when you give them a generator function that yields promises.

var getExample = Promise.coroutine(function* () {
// ^^^^^^^^^^^^^^^^^ Bluebird syntax
var resultA = yield promiseA(…);
// some processing
var resultB = yield promiseB(…);
// more processing
return // something using both resultA and resultB
});

This did work in Node.js since version 4.0, also a few browsers (or their dev editions) did support generator syntax relatively early.

ECMAScript 5

However, if you want/need to be backward-compatible you cannot use those without a transpiler. Both generator functions and async functions are supported by the current tooling, see for example the documentation of Babel on generators and async functions.

And then, there are also many other compile-to-JS languages
that are dedicated to easing asynchronous programming. They usually use a syntax similar to await, (e.g. Iced CoffeeScript), but there are also others that feature a Haskell-like do-notation (e.g. LatteJs, monadic, PureScript or LispyScript).

How do I access previous promise response in a .then() chain in axios?

You can use Promise.all:

axios.get(`/endpoint`) 
.then(
responseA =>
Promise.all([
responseA,
axios.get("/endpointB")
])
)
.then(
([responseA,responseB]) => {
console.log(responseA,responseB);
})
.catch((err) => {
console.log(err.message);
});

Get both return values of a promise chain

From the docs,

systeminformation.method() returns a promise. So you don't really need to wrap it inside a promise constructor, ie new Promise()

To get the cpu and temperature, since they are not dependent on each other, you can do either use parallel promises along with an async function or just parallel promises

async function getCpuAndTemperature() {
const [cpu, temperature] = await Promise.all([
si.cpu(),
si.cpuTemperature()
])

console.log(cpu, temperature)
}

or

function getCpuAndTemperature() {
return Promise.all([
si.cpu(),
si.cpuTemperature()
])
.then(([cpu, temperature]) => {
console.log(cpu, temperature)
})
}

Promise chaining: Use result from previous promise in next then callback

In my opinion, the zen of promises is all about figuring out they're really just asynchronous values. If you start using them as such these problems become simpler in many cases. It's not a silver bullet but it sure does help:

In ES5:

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.all([student, helpRequest]).then(function(results){
var student = results[0];
var helpRequest = results[1];
// access both here
});

In ES6, with all its features:

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.all([student, helpRequest]).then(([student, helpRequest]) => {
// access both here
});

In another richer promise library (bluebird):

var student = Student.find();
var helpRequest = student.then(HelpRequest.findByStudent);
Promise.join(student, helpRequest, function(student, helpRequest){
// access both here
});

How to access result from the previous promise in AngularJS promise chain?

You can put the then within the scope where user is still accessible (check closures)

authService.authenticate()
.then(function (user) {
Task.all({user: user})
.then(function (tasks) {
// How to access user object here?
})
})

From Kriskowal's Q documentation itself, both styles are equivalent. Angular's $q is based on Q

The only difference is nesting. It’s useful to nest handlers if you need to capture multiple input values in your closure.

How to chain and share prior results with Promises

There are a few models for dependent promises and passing data from one to the next. Which one works best depends upon whether you only need the previous data in the next call or whether you need access to all prior data. Here are several models:

Feed Result of One to the Next

callhttp(url1, data1).then(function(result1) {
// result1 is available here
return callhttp(url2, data2);
}).then(function(result2) {
// only result2 is available here
return callhttp(url3, data3);
}).then(function(result3) {
// all three are done now, final result is in result3
});

Assign Intermediate Results to Higher Scope

var r1, r2, r3;
callhttp(url1, data1).then(function(result1) {
r1 = result1;
return callhttp(url2, data2);
}).then(function(result2) {
r2 = result2;
// can access r1 or r2
return callhttp(url3, data3);
}).then(function(result3) {
r3 = result3;
// can access r1 or r2 or r3
});

Accumulate Results in One Object

var results = {};
callhttp(url1, data1).then(function(result1) {
results.result1 = result1;
return callhttp(url2, data2);
}).then(function(result2) {
results.result2 = result2;
// can access results.result1 or results.result2
return callhttp(url3, data3);
}).then(function(result3) {
results.result3 = result3;
// can access results.result1 or results.result2 or results.result3
});

Nest, so all Previous Results Can Be Accessed

callhttp(url1, data1).then(function(result1) {
// result1 is available here
return callhttp(url2, data2).then(function(result2) {
// result1 and result2 available here
return callhttp(url3, data3).then(function(result3) {
// result1, result2 and result3 available here
});
});
})

Break the Chain into Independent Pieces, Collect Results

If some parts of the chain can proceed independently, rather than one after the other, then you can launch them separately and use Promise.all() to know when those multiple pieces are done and you then will have all the data from those independent pieces:

var p1 = callhttp(url1, data1);
var p2 = callhttp(url2, data2).then(function(result2) {
return someAsync(result2);
}).then(function(result2a) {
return someOtherAsync(result2a);
});
var p3 = callhttp(url3, data3).then(function(result3) {
return someAsync(result3);
});
Promise.all([p1, p2, p3]).then(function(results) {
// multiple results available in results array
// that can be processed further here with
// other promises
});

Sequence with await in ES7

Since the promise chain is just a mechanism for sequencing asynchronous operations, in ES7, you can also use await and then the intermediate results are all available in the same scope (perhaps simpler than the separate scopes of the chained .then() handlers):

async function someFunction(...) {

const r1 = await callhttp(url1, data1);

// can use r1 here to formulate second http call
const r2 = await callhttp(url2, data2);

// can use r1 and r2 here to formulate third http call
const r3 = await callhttp(url3, data3);

// do some computation that has access to r1, r2 and r3
return someResult;
}

someFunction(...).then(result => {
// process final result here
}).catch(err => {
// handle error here
});

return Promise chain inside Promise then

The promise chain is being passed to the final .then, but the promise chain isn't returning anything: see your

.then((response) => {
objectDetail.push(response.data);
})

That function doesn't return anything. If you wanted to use objectDetail at the end of the chain without referencing the outer variable, return it as well:

.then((response) => {
objectDetail.push(response.data);
return objectDetail;
})

But note that

}).then((chain) => {
console.log(chain);
return chain;
})

is a bit redundant - unless you're only doing that in order to log the result, better just to leave it off entirely.

Your code would be clearer if you used Promise.all instead:

axios.get('apiendpoint/')
.then(({ data }) => Promise.all(
data.map(objectId => (axios.get(`apiendpoint/${objectId}`)
.then(res => res.data)
))
));


Related Topics



Leave a reply



Submit