How can I perform dynamic chaining in Javascript Promises, all the time I have seen only hardcoding of the calls for eg., (promise).then(request/functionName).then(request/functionName)
Promise chaining: Promise chaining is a syntax that allows you to chain together multiple asynchronous tasks in a specific order. This is great for complex code where one asynchronous task needs to be performed after the completion of a different asynchronous task.
JavaScript Promise Chaining Promises are useful when you have to handle more than one asynchronous task, one after another. For that, we use promise chaining. You can perform an operation after a promise is resolved using methods then() , catch() and finally() .
A Promise is in one of these states: pending: initial state, neither fulfilled nor rejected. fulfilled: meaning that the operation was completed successfully. rejected: meaning that the operation failed.
Approach 1: In this approach, we will use Promise. all() method which takes all promises in a single array as its input. As a result, this method executes all the promises in itself and returns a new single promise in which the values of all the other promises are combined together.
Given an array functions that all return promises, you can use reduce()
to run them sequentially:
var myAsyncFuncs = [ function (val) {return Promise.resolve(val + 1);}, function (val) {return Promise.resolve(val + 2);}, function (val) {return Promise.resolve(val + 3);}, ]; myAsyncFuncs.reduce(function (prev, curr) { return prev.then(curr); }, Promise.resolve(1)) .then(function (result) { console.log('RESULT is ' + result); // prints "RESULT is 7" });
The example above uses ES6 Promises but all promise libraries have similar features.
Also, creating the array of promise returning functions is usually a good candidate for using map()
. For example:
myNewOrmModels.map(function (model) { return model.save.bind(model); }).reduce(function (prev, curr) { return prev.then(curr); }, Promise.resolve()) .then(function (result) { console.log('DONE saving'); });
One option is to utilize the properties of objects and the ability to invoke them via strings.
I wrote a small sample Here and posted it below.
The idea is that you have the set of functions that you wish to run set in some namespace or object, as I did in 'myNamespace':
myNamespace = { "A": function() {return "A Function";}, "B": function() {return "B Function";}, "C": function() {return "C Function";} }
Then your main promise would run and somehow (via inputs, ajax, prompts, etc.) you would get the string value of the function you want to have run, which isn't known until runtime:
My main promise uses a prompt to get a letter from the user:
var answer = prompt('Starting. Please pick a letter: A,B,C'); if(myNamespace[answer] === undefined) { alert("Invalid choice!"); reject("Invalid choice of: " + answer); } else { resolve(answer); }
In the next 'then' I use that value (passed via the resolve function) to invoke the function:
.then(function(response) { funcToRun = myNamespace[response]();})
Finally, I output to html the result of my dynamic function call and I use some recursive fun to make it more interactive and demonstrate that it is dynamic:
.then(function(){ document.getElementById('result').innerHTML = funcToRun;}) .then(function(){ if(prompt("Run Again? (YES/NO)")==="YES") { doWork(); } });
myNamespace = { "A": function() {return "A Function";}, "B": function() {return "B Function";}, "C": function() {return "C Function";} } function doWork() { var funcToRun; new Promise(function(resolve,reject) { var answer = prompt('Starting. Please pick a letter: A,B,C'); if(myNamespace[answer] === undefined) { alert("Invalid choice!"); reject("Invalid choice of: " + answer); } else { resolve(answer); } }) .then(function(response) { funcToRun = myNamespace[response]();}) .then(function(){ document.getElementById('result').innerHTML = funcToRun;}) .then(function(){ if(prompt("Run Again? (YES/NO)")==="YES") { doWork(); } }); } doWork();
<div id="result"></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With