2016-12-10 104 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。