简体   繁体   中英

How to create a sequential promise loop with variable function calls

I need to somehow loop over the work array passed to _start then for each of the items in the array, I need to somehow call the corresponding function with the same name.

I don't have control over the number of items in work the array or the number of items, I do know that there will always be a corresponding function.

I don't want to call all the functions at the same time, once the first function resolves after 3 seconds, I then want to call the second function, once the second function resolves after 3 seconds I then want to call the third function. Once the third function resolves after another 3 seconds I want to call _done().

In this example each function takes 3 seconds to complete _done wont gete called for 9 seconds.

function _start(data){
    // Insert some kinda native magic loop
}


function _one(){
    return new Promise((resolve, reject) => {
        setTimeout(function(){ 
            resolve(1); 
        }, 3000);
    })
};


function _two(){
    return new Promise((resolve, reject) => {
        setTimeout(function(){ 
            resolve(2); 
        }, 3000);
    })
};

function _done(){
    console.log('All done in 9 seconds)
}


(function(){
    var work = ['_one', '_two', '_two'];
    _start(work);
})();

Given the order is dicated by the array, you can use reduce to aggregate the promises into a chain

const _start = (...actions) => {
  return actions.reduce((chain, action) => {
    const func = this[action];
    return chain.then(() => func());
  }, Promise.resolve());
}
...
_start('_one', '_two', '_three').then(() => console.log('All done'));

See it in action - the example appends an extra then to the chain just to output any results from the promises (probably outwith the scope of this question but something you may have to consider if getting data back is required).

Update

Can see you intend on invoking _start from a different context in which the functions are declared, this is fine but you need to make sure you set the correct context before hand ie

const self = this;
(function() {
  _start.bind(self)('_one', '_two', '_two');
})();

A function which creates a promise which sleeps:

const sleep = n => () => new Promise(resolve => setTimeout(resolve, n));

A function which sleeps after some input promise:

const sleepAfter = n => p => p.then(sleep(n));

A function which chains a bunch of promises, represented by functions:

const chain = (...promises) => promises.reduce((ret, promise) => ret.then(promise), 
  Promise.resolve());

Run a bunch of functions yielding promises, sleeping in between:

const _start = promises => chain(promises.map(sleepAfter(3000)));

Now just:

_start(_one, _two, _three).then(_done);

Try using this:

_one().then((firstResponse) {
      return_two();
}) .then((secondResponse) => {
 *second and first respone are already done*

});

Use promises then

_one().then((responseOne) => {
    return _two();
}).then((responseTwo) => {
    // _one & _two are done
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM