Delays between promises in promise chain

后端 未结 7 940
旧巷少年郎
旧巷少年郎 2020-12-14 20:35

Let\'s say I am using the following code to run a couple of promises in series:

let paramerterArr = [\'a\',\'b\',\'c\',\'d\',\'e\',\'f\']
parameterArr.reduce         


        
相关标签:
7条回答
  • 2020-12-14 20:43

    The following shows an example of how you might achieve a promise that doesn't block but waits for a designated time period:

    function timedPromise(ms, payload) {
        return new Promise(function(resolve) {
            setTimeout(function() {
                resolve(payload);
            }, ms);
        })
    }
    
    
    var time = Date.now();
    
    timedPromise(1000)
        .then(function() {
            console.log(time - Date.now());
            return timedPromise(2000);
        }).then(function() {
            console.log(time - Date.now());
            return timedPromise(3000);
        });
    

    So, depending on exactly what you want, you should be able to do something like this:

    let paramerterArr = ['a','b','c','d','e','f']
    parameterArr.reduce(function(promise, item) {
      return promise.then(function(result) {
        return mySpecialFunction(item);
      }).then(function(specialResult) {
        return timedPromise(50, specialResult);
      });
    }, Promise.resolve())
    
    0 讨论(0)
  • 2020-12-14 20:43

    Here is my complete solution for delayed promise sequences:

    
    function timeout_sequence_promise(promises = [], timeout = 200) {
    
        //fake promise used as buffer between promises from params
        const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    
        //we need to create array of all promises with delayed buffers
        let delayed_promises = [];
    
        let total = promises.length;
    
        let current = 0;
    
        //every odd promise will be buffer
        while (current < total) {
    
          delayed_promises.push(promises[current]);
          delayed_promises.push(delay(timeout));
    
          current++;
    
        }
    
        return Promise.all(delayed_promises).then((result) => {
    
          //we need to filter results from empty odd promises
          return result.filter((item, index) => (index+2)%2 === 0);
    
        });
    
    
      }
    
    

    It's receive array of promises and timeout delay in ms between them, as parameters.

    Hope, it will help you!

    0 讨论(0)
  • 2020-12-14 20:52

    since this seems to be a requirement of mySpecialFunction I'd implement it there. So that the function delays itself if it is called less than 50ms after the last call

    const delayBetweenCalls = (delay, fn) => {
        let lastCall = NaN;
        return function(/*...arguments*/){
            //this and arguments are both forwarded to fn
    
            return new Promise(resolve => {
                let poll = () => {
                    let delta = Date.now() - lastCall;
                    if(delta < delay){
                        setTimeout(poll, delta - delay);
                    }else{
                        lastCall = Date.now();
                        resolve( fn.apply(this, arguments) );
                    }
                }
                poll();
            })
        }
    }
    

    then:

    const mySpecialFunction = delayBetweenCalls(50, function(some, ...args){
        return someValueOrPromise;
    });
    
    //and your loop stays the same:
    parameterArr.reduce(function(promise, item) {
        return promise.then(function(result) {
            return mySpecialFunction(item);
        })
    }, Promise.resolve())
    

    so it doesn't matter where/how mySpecialFunction is called, there will always be a delay of at least 50ms before it runs the code inside the passed callback.

    0 讨论(0)
  • 2020-12-14 20:54

    To get a delay of at least 50ms, use Promise.all:

    function delay(t) {
      return new Promise(function(resolve) {
        setTimeout(resolve, t);
      });
    }
    parameterArr.reduce(function(promise, item) {
      return promise.then(function() {
        return Promise.all([
          mySpecialFunction(item),
          delay(50)
        ]);
      });
    }, Promise.resolve());
    
    0 讨论(0)
  • 2020-12-14 20:56

    The answers are good, but they wait too long since all the answers wait regardless of whether or not the actual operation took more than 50ms already.

    You can use Promise.all for it.

    const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
    let parameterArr = ['a','b','c','d','e','f'];
    parameterArr.reduce(function(promise, item) {
      return promise.then(function(result) {
        return Promise.all([delay(50), myPromise(item)]);
      });
    }, Promise.resolve());
    
    0 讨论(0)
  • 2020-12-14 21:04

    Here you go: https://jsbin.com/suvasox/edit?html,js,console

    let paramerterArr = ['a','b','c','d','e','f']
    paramerterArr.reduce((p, val) => {
      return p.then(() => {
        return new Promise((res) => {
          setTimeout(() => { res(mySpecialFunction(val)); }, 1000); 
        });
      });
    }, Promise.resolve());
    

    p has to be the result of the p.then(). Only that way you chain the promises.

    Notice, I changed it to 1000ms delay just for emphasis.

    0 讨论(0)
提交回复
热议问题