2016-12-10 160 views
6

比方说,我现在用的是下面的代码串联运行的一对夫妇承诺:延误承诺链

let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
    return mySpecialFunction(item); 
    }) 
}, Promise.resolve()) 

的代码简单地调用mySpecialFunction(它返回一个承诺),等待承诺解决,然后再次调用mySpecialFunction等。因此,该函数被调用一次为数组中的每个元素,按正确的顺序。

我怎样才能确保每次拨打电话mySpecialFunction(item)之间的延迟时间至少为50毫秒?

承诺以正确的顺序执行并且执行时间为mySpecialFunction每次都有所不同,这一点很重要。

我猜想同步睡眠是可行的,但我不打算在单独的线程中运行此代码,所以它会导致恼人的ui在浏览器中冻结。

我不确定setTimer是否可以以某种方式用于此目的。我的意思是我不能拖延诺言的回归。

+1

这可能有助于http://bluebirdjs.com/docs/api/promise.delay.html –

+0

我已经看到了,但我没有使用蓝鸟。我正在使用原生Promise。 (ECMA6) – Forivin

回答

8

答案很好,但是等待时间太长,因为所有的答案都等待,不管是否实际操作已经超过了50ms。您可以使用Promise.all

const delay = ms => new Promise(resolve => setTimeout(resolve, ms)); 
let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item) { 
    return promise.then(function(result) { 
    return Promise.all([delay(50), mySpecialFunction(item)]); 
    }) 
}, Promise.resolve()) 
+1

以37s击败我:-) – Bergi

1

下面显示了一个如何做到这一点不会阻止,但等待在指定的时间承诺的例子:

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); 
    }); 

所以,这取决于你想要什么,你应该能够做这样的事情:

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

一个非常方便实用的功能有大约就是我称之为delay()

function delay(t, val) { 
    return new Promise(function(resolve) { 
     if (t <= 0) { 
      resolve(val); 
     } else { 
      setTimeout(resolve.bind(null, val), t); 
     } 
    }); 
} 

然后,你可以用它在一个承诺链是这样的:

let paramerterArr = ['a','b','c','d','e','f'] 
parameterArr.reduce(function(promise, item, index) { 
    return promise.then(function(result) { 
    // no delay on first iteration 
    var delayT = index ? 50 : 0; 
    return delay(delayT, item).then(mySpecialFunction); 
    }) 
}, Promise.resolve()); 

你也可以做一个小工具功能与可选的延迟做连续迭代:

// delayT is optional (defaults to 0) 
function iterateSerialAsync(array, delayT, fn) { 
    if (!fn) { 
     fn = delayT; 
     delayT = 0; 
    } 
    array.reduce(function(p, item, index) { 
     return p.then(function() { 
      // no delay on first iteration 
      if (index === 0) delayT = 0; 
      return delay(delayT, item).then(fn) 
     }); 
    }, Promise.resolve()); 
} 

然后,你会像这样使用它:

iterateSerialAsync(paramerterArr, 50, mySpecialFunction).then(function(finalVal) { 
    // all done here 
}); 
1

她Ë你去: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的是p.then的结果()。只有这样你才能链接到承诺。

注意,为了强调,我将它改为1000ms延迟。

2

要获得至少 50毫秒的延迟,使用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

,因为这似乎是我实现它存在的mySpecialFunction的要求。这样的功能延误本身,如果它是在最后一次通话

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(); 
     }) 
    } 
} 

再经过所谓小于50ms:

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

所以它并不无论身在何处/如何mySpecialFunction被调用时,总是会有在传递回调内部的代码之前至少延迟50ms。