Using forEach to sequentially execute functions in Q - javascript

I'm attempting to run a series of functions based upon the Q API using their first strategy for sequences. This suggests the pattern:
var funcs = [foo, bar, baz, qux];
var result = Q(initialVal);
funcs.forEach(function (f) {
result = result.then(f);
});
return result;
What structure are each of the functions within the array meant to take? I am quite confused about when to use the return def.promise;. Is that simply always the last line? Will it frequently or always immediately follow def.resolve(someVar). Is something like this then ended structure?
function foo(f){
var def = Q.defer();
f++;
def.resolve(f);
return def.promise;
}
So that each subsequent function within the array will receive the newly calculated value of f: in this case, if var initialVal = 1; and four functions each incrementing f++, the returned result will be 4? How do I access that returned value? console.log(result) prints { state: 'pending' } .

What structure are each of the functions within the array meant to take?
Q.js allows promises to be created in several ways. For example :
function foo(value) {
var def = Q.defer();
def.resolve(value + 1);
return def.promise;
}
function foo(value) {
return Q(value + 1);
}
function foo(value) {
return Q.Promise(function(resolve, reject) {
resolve(value + 1);
});
}
Other Promise libs are similar, but not necessarily so flexible. Native js Promises must be constructed with the third of these approaches.
However, in the real world you will only rarely need to create your own Promise. You will typically be dealing with promise-returning lib methods that someone else has written. For example :
function foo(value) {
return lib.doSomethingAsync(value, and, other, params);
}
How do I access that returned value?
The code is easier to understand if member name "result" is replaced with "promise", and result.then(f) is rewritten with an anonymous function that calls f().
function performAsyncSequence() {
var promise = Q(initialVal);
funcs.forEach(function (f) {
promise = promise.then(function(previousResult) {
return f(previousResult);
});
});
return promise;
}
This is 100% equivalent to the code in the question, but now it should be clearer how the previous result is passed down the promise chain.
Accessing all previous promise results in the sequence is more complicated. The answers here discuss the subject comprehensively.

Related

why the variable is undefined

I could access the variable 'savedCards ' from the first promise, it has some value. Inside the second promise it's undefined but the variable 'eCard' has value. Please explain me why ?
saveCard(eCard: IEcards) {
var savedCards: IEcards[] = [];
this.storage.get("key").then((value) => {
if (value.saves == undefined) {
var saves = savedCards;
value.saves = saves;
}
savedCards = value.saveCard; // have value and can be accessed
console.log(savedCards);
}).then((data) => {
console.log(savedCards); // savedCards is undefined but eCard.id has value
this.globalProvider.IsCardExist(eCard.id, savedCards).then((data) => {
if (!data.response) {
this.globalProvider.AddEcardToStorage("saves", eCard);
}
});
});
}
When you need to access the intermediate values in your chain, you should split your chain apart in those single pieces that you need. Instead of attaching one callback and somehow trying to use its parameter multiple times, attach multiple callbacks to the same promise - wherever you need the result value.
function getExample() {
var a = promiseA(…);
var b = a.then(function(resultA) {
// some processing
return promiseB(…);
});
return Promise.all([a, b]).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
[Edit]
You want to know why, and here is the answer: ES6 came with 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.
Your code is resolving the second promise before the first one. You can not assure that your code will work as you want by using "then()". If you want a synchronous resolution, you should go for another way.
[Edit 2]
Try to use await and see if you are able to solve your problem. More info here: http://2ality.com/2017/08/promise-callback-data-flow.html

How to execute promises in series?

var promiseReturningFuncs = [];
for(var i = 0; i < 5; i++){
promiseReturningFuncs.push(askQuestion);
}
var programmers = [];
Promise.reduce(promiseReturningFuncs, function(resp, x) {
console.log(typeof resp);
if(typeof resp != "function") {
programmers.push(resp);
}
return x();
})
.then(function(resp) {
programmers.push(resp);
console.log(programmers);
});
My goal: execute the askQuestion function in series and resolve an array of objects created by that function. (this function must execute in series so that it can respond to user input)
So imagine that the askQuestion function returns a promise that resolves a object I want to add to an array.
This is my messy way of doing it.
I am looking to find a cleaner way of doing it, ideally, i wouldn't even need to push to an array, I would just have a final .then, where the response is an array.
Since you appear to be using the Bluebird promise library, you have a number of built-in options for sequencing your promise returning functions. You can use Promise.reduce(), Promise.map() with a concurrency value of 1, Promise.mapSeries or Promise.each(). If the iterator function returns a promise, all of these will wait for the next iteration until that promise resolves. Which to use depends more upon the mechanics of how your data is structured and what result you want (neither of which you actually show or describe).
Let's suppose you have an array of promise returning functions and you want to call them one at a time, waiting for the one to resolve before calling the next one. If you want all the results, then I'd suggest Promise.mapSeries():
let arrayOfPromiseReturningFunctions = [...];
// call all the promise returning functions in the array, one at a time
// wait for one to resolve before calling the next
Promise.mapSeries(arrayOfPromiseReturningFunctions, function(fn) {
return fn();
}).then(function(results) {
// results is an array of resolved results from all the promises
}).catch(function(err) {
// process error here
});
Promise.reduce() could also be used, but it would accumulate a single result, passing it from one to the next and end with one final result (like Array.prototype.reduce() does).
Promise.map() is a more general version of Promise.mapSeries() that lets you control the concurrency number (the number of async operations in flight at the same time).
Promise.each() will also sequence your functions, but does not accumulate a result. It assumes you either don't have a result or you are accumulating the result out-of-band or via side effects. I tend to not like to use Promise.each() because I don't like side effect programming.
You could solve this in pure JS using ES6 (ES2015) features:
function processArray(arr, fn) {
return arr.reduce(
(p, v) => p.then((a) => fn(v).then(r => a.concat([r]))),
Promise.resolve([])
);
}
It applies the function given to the array in series and resolves to an array of the results.
Usage:
const numbers = [0, 4, 20, 100];
const multiplyBy3 = (x) => new Promise(res => res(x * 3));
// Prints [ 0, 12, 60, 300 ]
processArray(numbers, multiplyBy3).then(console.log);
You'll want to double check browser compatibility but this works on reasonably current Chrome (v59), NodeJS (v8.1.2) and probably most others.
You can use recursion so that you can move to the next iteration in a then block.
function promiseToExecuteAllInOrder(promiseReturningFunctions /* array of functions */) {
var resolvedValues = [];
return new Promise(function(resolve, reject) {
function executeNextFunction() {
var nextFunction = promiseReturningFunctions.pop();
if(nextFunction) {
nextFunction().then(function(result) {
resolvedValues.push(result);
executeNextFunction();
});
} else {
resolve(resolvedValues);
}
}
executeNextFunction();
}
}
Executing one after another using a recursive function( in a non promise way):
(function iterate(i,result,callback){
if( i>5 ) callback(result);askQuestion().then(res=>iterate(i+1,result.concat([res]),callback);
})(0,[],console.log);
For shure this can be wrapped in a promise:
function askFive(){
return new Promise(function(callback){
(function iterate(i,result){
if( i>5 ) callback(result);askQuestion().then(res=>iterate(i+1,result.concat([res]),callback);
})(0,[],console.log);
});
}
askFive().then(console.log);
Or:
function afteranother(i,promise){
return new Promise(function(resolve){
if(!i) return resolve([]);
afteranother(i-1,promise).then(val=>promise().then(val2=>resolve(val.concat([val2])));
});
}
afteranother(5,askQuestion).then(console.log);

Flattening promise chain with readable function name

I saw promise implementation in Handling multiple catches in promise chain which produce a very readable chain
return validateInput
.then(checkLoginPermission)
.then(checkDisableUser)
.then(changePassword);
However, in order to do this each function needs to return a value instead of a Promise? Since Promise can resolves to either value or a Promise so this is not a problem. My goal is to turn every function to have readable clear logic as such.
The problem occurs when trying to unwind the nested promise function
return validateInput
.then(function(resultA) {
return checkLoginPermission
.then (function(resultB) {
// Do something with resultA
})
});
Imagine the original implementation involves accessing the value from previous promise. With nested promise, it is easily achievable. But with flatten chain, I would need to break up each function like this
function validateInput = function (resultA ) {
return Promise.resolve({resultA : resultA, resultB :
}
function checkLoginPermission = function (mix ) {
let resultA = mix.resultA;
let resultB = mix.resultB
//Do something with resultA
...
}
This is worse when the last function in the chain rely on something from the very beginning. That means the value have to be passed down from the beginning of the chain even if it was not used.
So am I accidentally stepping on some kind of anti-pattern that might affect performance? How else can I achieve good readability without all these hassles?
This is actually where async and await come in. It's good when you need results across multiple asynchronous calls/promises to be in scope. If you can use that, I'd say try it.
async function foo () {
const input = await validateInput()
const hasPermission = await checkLoginPermission(input)
const result = await checkDisableUser(hasPermission)
return await changePassword(result)
}
Just pass the variables into what function as they need to be. Just showing an example there. I was also a bit unsure of how you're setting validateInput, i think you need to put await infront of the function call itself.
If you cannot use async/await, I usually go with your 2nd code snippet, or define the higher scope variables ontop:
let resultA
return validateInput
.then(function(result) {
resultA = result
return checkLoginPermission
.then (function(resultB) {
// Do something with resultA
})
});
Promises are pattern, related to functional programming, there direct passing data from one function to other is a basic (it's called compose, here examples: http://scott.sauyet.com/Javascript/Talk/Compose/2013-05-22/). So it's not anti-pattern by no means.
I can't see any problem in such pattern. You can pass any data you want to next Promises and in nested Promises grab what they need. It's preety transparent and clear:
function validateInput() {
return Promise.resolve({resultA: 1});
}
function checkLoginPermission(result) {
return new Promise(function(resolve, reject) {
// ...
// code
// ...
result.resultB = 2;
return resolve(result);
});
}
function checkDisableUser(result) {
return new Promise(function(resolve, reject) {
// grab some data from previous function
let resultB = result.resultB;
// ...
// code
// ...
result.resultC = 3;
return resolve(result);
});
}
function changePassword(result) {
return new Promise(function(resolve, reject) {
// grab some data from previous functions
let resultB = result.resultB;
let resultC = result.resultC;
// ...
// code
// ...
result.resultD = resultB * resultC;
return resolve(result);
});
}
validateInput()
.then(checkLoginPermission)
.then(checkDisableUser)
.then(changePassword);
Also you can collect data in some variable, declared before Promises and so you will not have to pass result. But it will destroy functional nature of Promises.
The inner .then(/* ... */) callbacks can return either a primitive value or a Promise that resolves to some value. If it is another promise then the next .then won't start until the inner promise is resolved. Essentially, Promises always resolve to a non-promise type. If you resolve or return another Promise, it will be automatically unwrapped.
I would like to propose a solution using ramda.js#pipeP().
The good thing about this function is that it resolves promises sequentially.
We can rewrite your example using pipeP():
import pipeP from 'ramda/src/pipeP'
pipeP([
checkLoginPermission,
checkDisableUser,
changePassword
])(initialValue)
.then(responseChangePassword => { ... })
The results of a previous promise are passed to the following one.

Javascript Promise Object: how to store the success callback at different points [duplicate]

I have restructured my code to 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?
});
}
Break the chain
When you need to access the intermediate values in your chain, you should split your chain apart in those single pieces that you need. Instead of attaching one callback and somehow trying to use its parameter multiple times, attach multiple callbacks to the same promise - wherever you need the result value. Don't forget, a promise just represents (proxies) a future value! Next to deriving one promise from the other in a linear chain, use the promise combinators that are given to you by your library to build the result value.
This will result in a very straightforward control flow, clear composition of functionalities and therefore easy modularisation.
function getExample() {
var a = promiseA(…);
var b = a.then(function(resultA) {
// some processing
return promiseB(…);
});
return Promise.all([a, b]).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
Instead of the parameter destructuring in the callback after Promise.all that only became avail­able with ES6, in ES5 the then call would be replaced by a nifty helper method that was provided by many promise libraries (Q, Bluebird, when, …): .spread(function(resultA, resultB) { ….
Bluebird also features a dedicated join function to replace that Promise.all+spread combination with a simpler (and more efficient) construct:
…
return Promise.join(a, b, function(resultA, resultB) { … });
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).
Synchronous inspection
Assigning promises-for-later-needed-values to variables and then getting their value via synchronous inspection. The example uses bluebird's .value() method but many libraries provide similar method.
function getExample() {
var a = promiseA(…);
return a.then(function() {
// some processing
return promiseB(…);
}).then(function(resultB) {
// a is guaranteed to be fulfilled here so we can just retrieve its
// value synchronously
var aValue = a.value();
});
}
This can be used for as many values as you like:
function getExample() {
var a = promiseA(…);
var b = a.then(function() {
return promiseB(…)
});
var c = b.then(function() {
return promiseC(…);
});
var d = c.then(function() {
return promiseD(…);
});
return d.then(function() {
return a.value() + b.value() + c.value() + d.value();
});
}
Nesting (and) closures
Using closures for maintaining the scope of variables (in our case, the success callback function parameters) is the natural JavaScript solution. With promises, we can arbitrarily nest and flatten .then() callbacks - they are semantically equivalent, except for the scope of the inner one.
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(function(resultB) {
// more processing
return // something using both resultA and resultB;
});
});
}
Of course, this is building an indentation pyramid. If indentation is getting too large, you still can apply the old tools to counter the pyramid of doom: modularize, use extra named functions, and flatten the promise chain as soon as you don't need a variable any more.
In theory, you can always avoid more than two levels of nesting (by making all closures explicit), in practise use as many as are reasonable.
function getExample() {
// preprocessing
return promiseA(…).then(makeAhandler(…));
}
function makeAhandler(…)
return function(resultA) {
// some processing
return promiseB(…).then(makeBhandler(resultA, …));
};
}
function makeBhandler(resultA, …) {
return function(resultB) {
// more processing
return // anything that uses the variables in scope
};
}
You can also use helper functions for this kind of partial application, like _.partial from Underscore/lodash or the native .bind() method, to further decrease indentation:
function getExample() {
// preprocessing
return promiseA(…).then(handlerA);
}
function handlerA(resultA) {
// some processing
return promiseB(…).then(handlerB.bind(null, resultA));
}
function handlerB(resultA, resultB) {
// more processing
return // anything that uses resultA and resultB
}
Explicit pass-through
Similar to nesting the callbacks, this technique relies on closures. Yet, the chain stays flat - instead of passing only the latest result, some state object is passed for every step. These state objects accumulate the results of the previous actions, handing down all values that will be needed later again plus the result of the current task.
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(b => [resultA, b]); // function(b) { return [resultA, b] }
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
Here, that little arrow b => [resultA, b] is the function that closes over resultA, and passes an array of both results to the next step. Which uses parameter destructuring syntax to break it up in single variables again.
Before destructuring became available with ES6, a nifty helper method called .spread() was pro­vi­ded by many promise libraries (Q, Bluebird, when, …). It takes a function with multiple parameters - one for each array element - to be used as .spread(function(resultA, resultB) { ….
Of course, that closure needed here can be further simplified by some helper functions, e.g.
function addTo(x) {
// imagine complex `arguments` fiddling or anything that helps usability
// but you get the idea with this simple one:
return res => [x, res];
}
…
return promiseB(…).then(addTo(resultA));
Alternatively, you can employ Promise.all to produce the promise for the array:
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return Promise.all([resultA, promiseB(…)]); // resultA will implicitly be wrapped
// as if passed to Promise.resolve()
}).then(function([resultA, resultB]) {
// more processing
return // something using both resultA and resultB
});
}
And you might not only use arrays, but arbitrarily complex objects. For example, with _.extend or Object.assign in a different helper function:
function augment(obj, name) {
return function (res) { var r = Object.assign({}, obj); r[name] = res; return r; };
}
function getExample() {
return promiseA(…).then(function(resultA) {
// some processing
return promiseB(…).then(augment({resultA}, "resultB"));
}).then(function(obj) {
// more processing
return // something using both obj.resultA and obj.resultB
});
}
While this pattern guarantees a flat chain and explicit state objects can improve clarity, it will become tedious for a long chain. Especially when you need the state only sporadically, you still have to pass it through every step. With this fixed interface, the single callbacks in the chain are rather tightly coupled and inflexible to change. It makes factoring out single steps harder, and callbacks cannot be supplied directly from other modules - they always need to be wrapped in boilerplate code that cares about the state. Abstract helper functions like the above can ease the pain a bit, but it will always be present.
Mutable contextual state
The trivial (but inelegant and rather errorprone) solution is to just use higher-scope variables (to which all callbacks in the chain have access) and write result values to them when you get them:
function getExample() {
var resultA;
return promiseA(…).then(function(_resultA) {
resultA = _resultA;
// some processing
return promiseB(…);
}).then(function(resultB) {
// more processing
return // something using both resultA and resultB
});
}
Instead of many variables one might also use an (initially empty) object, on which the results are stored as dynamically created properties.
This solution has several drawbacks:
Mutable state is ugly, and global variables are evil.
This pattern doesn't work across function boundaries, modularising the functions is harder as their declarations must not leave the shared scope
The scope of the variables does not prevent to access them before they are initialized. This is especially likely for complex promise constructions (loops, branching, excptions) where race conditions might happen. Passing state explicitly, a declarative design that promises encourage, forces a cleaner coding style which can prevent this.
One must choose the scope for those shared variables correctly. It needs to be local to the executed function to prevent race conditions between multiple parallel invocations, as would be the case if, for example, state was stored on an instance.
The Bluebird library encourages the use of an object that is passed along, using their bind() method to assign a context object to a promise chain. It will be accessible from each callback function via the otherwise unusable this keyword. While object properties are more prone to undetected typos than variables, the pattern is quite clever:
function getExample() {
return promiseA(…)
.bind({}) // Bluebird only!
.then(function(resultA) {
this.resultA = resultA;
// some processing
return promiseB(…);
}).then(function(resultB) {
// more processing
return // something using both this.resultA and resultB
}).bind(); // don't forget to unbind the object if you don't want the
// caller to access it
}
This approach can be easily simulated in promise libraries that do not support .bind (although in a somewhat more verbose way and cannot be used in an expression):
function getExample() {
var ctx = {};
return promiseA(…)
.then(function(resultA) {
this.resultA = resultA;
// some processing
return promiseB(…);
}.bind(ctx)).then(function(resultB) {
// more processing
return // something using both this.resultA and resultB
}.bind(ctx));
}
A less harsh spin on "Mutable contextual state"
Using a locally scoped object to collect the intermediate results in a promise chain is a reasonable approach to the question you posed. Consider the following snippet:
function getExample(){
//locally scoped
const results = {};
return promiseA(paramsA).then(function(resultA){
results.a = resultA;
return promiseB(paramsB);
}).then(function(resultB){
results.b = resultB;
return promiseC(paramsC);
}).then(function(resultC){
//Resolve with composite of all promises
return Promise.resolve(results.a + results.b + resultC);
}).catch(function(error){
return Promise.reject(error);
});
}
Global variables are bad, so this solution uses a locally scoped variable which causes no harm. It is only accessible within the function.
Mutable state is ugly, but this does not mutate state in an ugly manner. The ugly mutable state traditionally refers to modifying the state of function arguments or global variables, but this approach simply modifies the state of a locally scoped variable that exists for the sole purpose of aggregating promise results...a variable that will die a simple death once the promise resolves.
Intermediate promises are not prevented from accessing the state of the results object, but this does not introduce some scary scenario where one of the promises in the chain will go rogue and sabotage your results. The responsibility of setting the values in each step of the promise is confined to this function and the overall result will either be correct or incorrect...it will not be some bug that will crop up years later in production (unless you intend it to!)
This does not introduce a race condition scenario that would arise from parallel invocation because a new instance of the results variable is created for every invocation of the getExample function.
Example is available on jsfiddle
Node 7.4 now supports async/await calls with the harmony flag.
Try this:
async function getExample(){
let response = await returnPromise();
let response2 = await returnPromise2();
console.log(response, response2)
}
getExample()
and run the file with:
node --harmony-async-await getExample.js
Simple as can be!
Another answer, using babel-node version <6
Using async - await
npm install -g babel#5.6.14
example.js:
async function getExample(){
let response = await returnPromise();
let response2 = await returnPromise2();
console.log(response, response2)
}
getExample()
Then, run babel-node example.js and voila!
This days, I also hava meet some questions like you. At last, I find a good solution with the quesition, it's simple and good to read. I hope this can help you.
According to how-to-chain-javascript-promises
ok, let's look at the code:
const firstPromise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('first promise is completed');
resolve({data: '123'});
}, 2000);
});
};
const secondPromise = (someStuff) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('second promise is completed');
resolve({newData: `${someStuff.data} some more data`});
}, 2000);
});
};
const thirdPromise = (someStuff) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log('third promise is completed');
resolve({result: someStuff});
}, 2000);
});
};
firstPromise()
.then(secondPromise)
.then(thirdPromise)
.then(data => {
console.log(data);
});
I am not going to use this pattern in my own code since I'm not a big fan of using global variables. However, in a pinch it will work.
User is a promisified Mongoose model.
var globalVar = '';
User.findAsync({}).then(function(users){
globalVar = users;
}).then(function(){
console.log(globalVar);
});
Another answer, using sequential executor nsynjs:
function getExample(){
var response1 = returnPromise1().data;
// promise1 is resolved at this point, '.data' has the result from resolve(result)
var response2 = returnPromise2().data;
// promise2 is resolved at this point, '.data' has the result from resolve(result)
console.log(response, response2);
}
nynjs.run(getExample,{},function(){
console.log('all done');
})
Update: added working example
function synchronousCode() {
var urls=[
"https://ajax.googleapis.com/ajax/libs/jquery/1.7.0/jquery.min.js",
"https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js",
"https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"
];
for(var i=0; i<urls.length; i++) {
var len=window.fetch(urls[i]).data.text().data.length;
// ^ ^
// | +- 2-nd promise result
// | assigned to 'data'
// |
// +-- 1-st promise result assigned to 'data'
//
console.log('URL #'+i+' : '+urls[i]+", length: "+len);
}
}
nsynjs.run(synchronousCode,{},function(){
console.log('all done');
})
<script src="https://rawgit.com/amaksr/nsynjs/master/nsynjs.js"></script>
When using bluebird, you can use .bind method to share variables in promise chain:
somethingAsync().bind({})
.spread(function (aValue, bValue) {
this.aValue = aValue;
this.bValue = bValue;
return somethingElseAsync(aValue, bValue);
})
.then(function (cValue) {
return this.aValue + this.bValue + cValue;
});
please check this link for further information:
http://bluebirdjs.com/docs/api/promise.bind.html
function getExample() {
var retA, retB;
return promiseA(…).then(function(resultA) {
retA = resultA;
// Some processing
return promiseB(…);
}).then(function(resultB) {
// More processing
//retA is value of promiseA
return // How do I gain access to resultA here?
});
}
easy way :D
I think you can use hash of RSVP.
Something like as below :
const mainPromise = () => {
const promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('first promise is completed');
resolve({data: '123'});
}, 2000);
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
console.log('second promise is completed');
resolve({data: '456'});
}, 2000);
});
return new RSVP.hash({
prom1: promise1,
prom2: promise2
});
};
mainPromise()
.then(data => {
console.log(data.prom1);
console.log(data.prom2);
});
Solution:
You can put intermediate values in scope in any later 'then' function explicitly, by using 'bind'. It is a nice solution that doesn't require changing how Promises work, and only requires a line or two of code to propagate the values just like errors are already propagated.
Here is a complete example:
// Get info asynchronously from a server
function pGetServerInfo()
{
// then value: "server info"
} // pGetServerInfo
// Write into a file asynchronously
function pWriteFile(path,string)
{
// no then value
} // pWriteFile
// The heart of the solution: Write formatted info into a log file asynchronously,
// using the pGetServerInfo and pWriteFile operations
function pLogInfo(localInfo)
{
var scope={localInfo:localInfo}; // Create an explicit scope object
var thenFunc=p2.bind(scope); // Create a temporary function with this scope
return (pGetServerInfo().then(thenFunc)); // Do the next 'then' in the chain
} // pLogInfo
// Scope of this 'then' function is {localInfo:localInfo}
function p2(serverInfo)
{
// Do the final 'then' in the chain: Writes "local info, server info"
return pWriteFile('log',this.localInfo+','+serverInfo);
} // p2
This solution can be invoked as follows:
pLogInfo("local info").then().catch(err);
(Note: a more complex and complete version of this solution has been tested, but not this example version, so it could have a bug.)
What I learn about promises is to use it only as return values avoid referencing them if possible. async/await syntax is particularly practical for that. Today all latest browsers and node support it: https://caniuse.com/#feat=async-functions , is a simple behavior and the code is like reading synchronous code, forget about callbacks...
In cases I do need to reference a promises is when creation and resolution happen at independent/not-related places. So instead an artificial association and probably an event listener just to resolve the "distant" promise, I prefer to expose the promise as a Deferred, which the following code implements it in valid es5
/**
* Promise like object that allows to resolve it promise from outside code. Example:
*
```
class Api {
fooReady = new Deferred<Data>()
private knower() {
inOtherMoment(data=>{
this.fooReady.resolve(data)
})
}
}
```
*/
var Deferred = /** #class */ (function () {
function Deferred(callback) {
var instance = this;
this.resolve = null;
this.reject = null;
this.status = 'pending';
this.promise = new Promise(function (resolve, reject) {
instance.resolve = function () { this.status = 'resolved'; resolve.apply(this, arguments); };
instance.reject = function () { this.status = 'rejected'; reject.apply(this, arguments); };
});
if (typeof callback === 'function') {
callback.call(this, this.resolve, this.reject);
}
}
Deferred.prototype.then = function (resolve) {
return this.promise.then(resolve);
};
Deferred.prototype.catch = function (r) {
return this.promise.catch(r);
};
return Deferred;
}());
transpiled form a typescript project of mine:
https://github.com/cancerberoSgx/misc-utils-of-mine/blob/2927c2477839f7b36247d054e7e50abe8a41358b/misc-utils-of-mine-generic/src/promise.ts#L31
For more complex cases I often use these guy small promise utilities without dependencies tested and typed. p-map has been useful several times. I think he covered most use cases:
https://github.com/sindresorhus?utf8=%E2%9C%93&tab=repositories&q=promise&type=source&language=

How to implement dependency between asynchronous functions in JavaScript?

As a simplified case, I have two async functions, foo and bar. bar needs the result of foo, i.e. bar depends on foo. I have no idea about which function will be called first.
If bar is invoked first, bar will call foo and start itself right after foo is done.
If foo is invoked first and done, bar can use the result of foo.
If foo is invoked first and bar is invoked before foo is done, bar needs to wait for foo's result. (Don't invoke a new call to foo, just wait for the already-fired call to foo)
How can I achieve this?
Is it possible to register an async function dependency chain (something like the dependency in require.js define['foo'], function() { bar(); })?
Can I use $.deferred() to achieve it?
How?
In circumstances like this, the standard approach is to cache the lower level promise.
Typically you will establish, in some suitable outer scope, a js plain object as a promise cache, and always look there first before calling your async process.
var promiseCache = {};
function foo() {
if(!promiseCache.foo) {
promiseCache.foo = doSomethingAsync();
}
return promiseCache.foo;
}
function bar() {
return foo().then(doSomethingElseAsync);
}
Of course, there's nothing to prevent you also caching the higher level promise, if appropriate.
function bar() {
if(!promiseCache.bar) {
promiseCache.bar = foo().then(doSomethingElseAsync);
}
return promiseCache.bar;
}
EDIT: forceRefresh feature
You can force a function to refresh its cached promise by passing an (extra) parameter.
function foo(any, number, of, other, arguments, forceRefresh) {
if(forceRefresh || !promiseCache.foo) {
promiseCache.foo = doSomethingAsync();
}
return promiseCache.foo;
}
By making forceRefresh the last argument, leaving it out is the same as passing false and foo will use the cached promise if available. Alternatively, pass true to guarantee that doSomethingAsync() be called and the cached value be refreshed.
EDIT 2: setName()/getName()
With the forceRefresh mechanism in place in getName() :
setName(newName).then(getName.bind(null, true)); //set new name then read it back using forceRefresh.
Alternatively, omit the forceRefresh mechanism and, assuming the cache property to be promiseCache.name :
setName(newName).then(function() {
promiseCache.name = $.when(newName);//update the cache with a simulated `getName()` promise.
});
The first method is more elegant, the second more efficient.
You can simply think of both functions as independent. That way, you don't go daisy-chaining dependencies that operate asynchronously. You can then have one other module that uses them.
Since they do async stuff, consider using promises. You can use jQuery's deferreds for compatibility. Think of deferreds as read/write while promises are read-only.
// foo.js
define(function(){
return function(){
return new Promise(function(resolve, reject){
// Do async stuff. Call resolve/reject accordingly
});
};
});
// bar.js
define(function(){
return function(){
return new Promise(function(resolve, reject){
// Do async stuff. Call resolve/reject accordingly
});
};
});
// Your code (Excuse the CommonJS format. Personal preference)
define(function(require){
// Require both functions
var foo = require('foo');
var bar = require('bar');
// Use them
foo(...).then(function(response){
return bar();
}).then(function(){
// all done
});;
});
Try creating an object property with possible values undefined , "pending" , true ; call deferred.resolve() when obj.active is true , deferred.reject() when obj.active is "pending"
var res = {
active: void 0
};
var foo = function foo(state) {
var t;
var deferred = function(type) {
return $.Deferred(function(dfd) {
if (res.active === "pending" || state && state === "pending") {
res.active = "pending";
dfd.rejectWith(res, [res.active])
} else {
res.active = state || "pending";
t = setInterval(function() {
console.log(res.active)
}, 100);
setTimeout(function() {
clearInterval(t)
res.active = true;
dfd.resolveWith(res, [res.active])
}, 3000);
}
return dfd.promise()
})
.then(function(state) {
console.log("foo value", state);
return state
}, function(err) {
console.log("foo status", err)
return err
})
}
return deferred()
}
var bar = function bar(result) {
var deferred = function(type) {
return $.Deferred(function(dfd) {
if (result && result === true) {
setTimeout(function() {
dfd.resolveWith(result, [true])
}, 1500)
} else {
dfd.rejectWith(res, [res.active || "pending"])
};
return dfd.promise()
})
}
return deferred().then(function(data) {
console.log("bar value", data);
}, function(err) {
console.log("bar status", err);
})
}
$("button").click(function() {
$(this).is(":first")
? foo().then(bar, bar)
: bar(res.active === true ? res.active : "pending")
.then(foo, foo).then(bar, bar)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<button>foo</button>
<button>bar</button>
Not sure I understood correctly the question. But here is my take at it:
Put you function foo into a variable
var foo_fn = function foo(foo_args){// Your async code goes here}
foo is async and returns something at some point. In your definition of foo, I recommend that you use promises, the concept is designed to manage composition of asynchronous functions in a clean and scalable way. jQuery implementation of the concept is convenient in a lot of simple use cases but suffers from some drawbacks which make it interesting for you at some point to use one of the many promises library which follow the Promises/A specification. For more information, you can refer to :
Cf. https://thewayofcode.wordpress.com/2013/01/22/javascript-promises-and-why-jquery-implementation-is-broken/ and https://blog.domenic.me/youre-missing-the-point-of-promises
so, say foo takes args, and returns a promise which later resolves into some value.
var foo_fn = function foo(foo_args) {
return foo_fn.promise = new RSVP.Promise (resolve, reject) {
// Your async code goes here
}
}
Here I use the RSVP promise library but any promise library following the Promises/A specification could do the job.
When bar is called, you can just do:
function bar (bar_args) {
var foo_promise = foo_fn.promise;
// if foo was called, whether the computation is in progress or finished,
// the foo_fn.promise field will be non-empty, as foo returns immediately
// with a promise anytime it is called
``
if (!foo.promise) {
// foo has not yet been called so call it
foo_promise = foo(foo_args);
}
foo_promise.then (function (foo_result) {/*some async code here*/})
}
NOTE : That solution is quite similar to the one proposed by Roamer-1888. One difference is that in Roamer proposal, the foo function will always return the same value after performing once its asyncronous computation. Don't know if this is the intended behaviour. In my implementation, foo executes the async. computation every time it is called. bar will use the latest computed value that is stored in the field foo_fn.promise. Older computations are lost, possible computation in progress is not taken into account.
If you are going to have this pattern often used in your code, you can also create a function working on the model of the define
function in require.js.
You will need :
a registry to hold the dependencies functions (foo in your example)
the dependant function (bar in your example) will need to accept the dependencies functions computed value as part of their signature. For example, a hash of the dependencies could be passed as first parameter, so bar signature could be: {foo: foo_result}, other_bar_args...
the dependencies function must follow the model of my previous answer, i.e. register their promise value as a property on themselves when they execute.
Reminder : you need to name those dependencies functions to reference them inside their body, and then add that object to the registry.
In the define function body, you wrap the dependent function into another one which :
Get all dependencies from the registry
Get all dependencies values, executing the dependencies when necessary (similarly to my previous answer). This means you end up having a list of promises, whose results you then congregate together (RSVP.hash for example with RSVP promise library). I believe jQuery has a similar function with jQuery.when
you call the dependent function (bar) with this hash of results as a first argument, other arguments being the same as the wrapped function
that wrapped function is the new bar, so when bar is called, it will be the wrapped function which will be called.
A bit lengthy but it should work. If you want to see some code, let me know if this is what you were looking for. In any case, if you are going to have complex async. in your code, it could be interesting for you to use a compliant promise library. $.deferred is also to be used only when you have nothing better at sight as it makes it harder for you to track the behaviour of your functions : you need to keep track of all places where this deferred appears to be able to reason about your program.

Categories