Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Chaining in Javascript Promises

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)

like image 640
Ramu Ajay Avatar asked Jun 15 '15 19:06

Ramu Ajay


People also ask

What is Promise chaining in JavaScript?

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.

Can we chain promises in JavaScript?

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() .

What are the 3 states of a JavaScript Promise?

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.

How do you write multiple promises in JavaScript?

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.


2 Answers

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'); }); 
like image 171
wuher Avatar answered Sep 27 '22 00:09

wuher


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>
like image 42
JasonWilczak Avatar answered Sep 25 '22 00:09

JasonWilczak