Thursday, 7 December 2017

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

itemprop="text">

I have restructured my code to href="https://en.wikipedia.org/wiki/Futures_and_promises">promises, and
built a wonderful long flat promise chain, consisting of
multiple .then() callbacks. In the end I want to return some
composite value, and need to access multiple intermediate promise
results
. However the resolution values from the middle of the sequence
are not in scope in the last callback, how do I access
them?



function getExample()
{
return promiseA(…).then(function(resultA) {
// Some
processing
return promiseB(…);
}).then(function(resultB)
{
// More processing
return // How do I gain access to resultA
here?
});
}


Answer






Of course, this problem
was recognized by the language designers as well. They did a lot of work and the href="http://tc39.github.io/ecmascript-asyncawait/" rel="noreferrer">async functions
proposal finally made it
into



ECMAScript
8



You don't need a single
then invocation or callback function any more, 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 href="http://davidwalsh.name/es6-generators" rel="noreferrer">generator
functions, which allow to break 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 href="https://github.com/tj/co" rel="noreferrer">co or href="http://taskjs.org/" rel="noreferrer">task.js), but also many promise
libraries have helper functions ( href="https://github.com/kriskowal/q/wiki/API-Reference#generators"
rel="noreferrer">Q, href="http://bluebirdjs.com/docs/api/generators.html"
rel="noreferrer">Bluebird, href="https://github.com/cujojs/when/blob/master/docs/api.md#es6-generators"
rel="noreferrer">when, …) that do href="https://stackoverflow.com/a/23554399/1048572">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
backwards-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 href="http://babeljs.io/learn-es2015/#ecmascript-2015-features-generators"
rel="noreferrer">generators and href="http://babeljs.io/docs/plugins/syntax-async-functions" rel="noreferrer">async
functions.



And then, there are also
many other href="https://github.com/jashkenas/coffeescript/wiki/List-of-languages-that-compile-to-JS#synchronous-to-asynchronous-javascript-compilers-cps"
rel="noreferrer">compile-to-JS languages
that are dedicated to
easing asynchronous programming. They usually use a syntax similar to
await, (e.g. href="http://maxtaco.github.io/coffee-script/" rel="noreferrer">Iced
CoffeeScript), but there are also others that feature a Haskell-like
do-notation (e.g. rel="noreferrer">LatteJs, href="https://www.npmjs.com/package/monadic" rel="noreferrer">monadic,
PureScript or
rel="noreferrer">LispyScript).



No comments:

Post a Comment

php - file_get_contents shows unexpected output while reading a file

I want to output an inline jpg image as a base64 encoded string, however when I do this : $contents = file_get_contents($filename); print ...