由於 Promise 是 Asynchronous,因此回傳時間不確定,若想實作出超過指定時間就 Timeout,可使用 Promise.race()
實作。
Version
macOS Mojave 10.14.6
VS Code 1.38.1
Quokka 1.0.253
ECMAScript 2015
Promise.race()
import { resolveAfter, log } from 'wink-fp'
let data = [
resolveAfter(1000)(1),
resolveAfter(2000)(2),
resolveAfter(3000)(3),
]
Promise.race(data)
.then(log)
.catch(log)
第 3 行
let data = [
resolveAfter(1000)(1),
resolveAfter(2000)(2),
resolveAfter(3000)(3),
]
data
內有 3
個 promise,依次在 1
秒、2
秒、3
秒後產生。
第 9 行
Promise.race(data)
.then(log)
使用 Promise.race()
從兩個 promise 中選擇 最先產生
的 promise。
無論是 fulfilled project 或 rejected promise,只要是最先 settled promise 即可
Timeout Promise
import { resolveAfter, log, rejectAfter, error } from 'wink-fp'
let data = resolveAfter(1000)(1)
let timeout = rejectAfter(500)(new Error('Timeout after 500 ms'))
Promise.race([data, timeout])
.then(log)
.catch(error)
若想要實作非同步只等待一段時間,超過時間就 timeout 放棄,可另外建立一個 rejected promise 由 Promise.race()
決定。
Timeout Promise
import { resolveAfter, log, error } from 'wink-fp'
let timeout = ms => ps => {
let timeoutID;
let timeoutPromise = new Promise((_, reject) => {
timeoutID = setTimeout(() => {
reject(new Error(`Timeout after ${ms} ms`))
}, ms);
});
return Promise.race([ ps, timeoutPromise ])
.finally(() => clearTimeout(timeoutID));
};
let promise0 = resolveAfter(1000)(1);
timeout(500)(promise0)
.then(log)
.catch(error);
亦可以相同原理實作出 timeout()
。
第 3 行
let timeout = ms => ps => {
let timeoutID;
let timeoutPromise = new Promise((_, reject) => {
timeoutID = setTimeout(() => {
reject(new Error(`Timeout after ${ms} ms`))
}, ms);
});
return Promise.race([ ps, timeoutPromise ])
.finally(() => clearTimeout(timeoutID));
};
timeout()
可建立一個 timeout promise,並與傳入的 promise 透過 Promise.race()
比較:
- 若傳入 fulfilled promise 比 timeout promise 快,則回傳 fulfilled promise
- 若傳入 fulfilled promise 比 timeut promise 快,則回傳 rejected promise
Conclusion
Promise.race()
一般不常使用,但透過Promise.race()
與自行建立的 timeout rejected promise 比較,可實作出若超過時間 timeout 就放棄 promise 的需求
Reference
Marius Schulz, Wait for the Fastest JavaScript Promise to Settle with Promise.race()
MDN, Promise.race()