一.前言
阅读本文,你将学到:
1. 学会如何实现一个比较完善的 delay 函数4. 等等
# 推荐克隆我的项目,保证与文章同步 git clone https://github.com/lxchuan12/delay-analysis.git # npm i -g yarn cd delay-analysis/delay && yarn i # VSCode 直接打开当前项目 # code . # 我写的例子都在 examples 这个文件夹中,可以启动服务本地查看调试 # 在 delay-analysis 目录下 npx http-server examples # 打开 http://localhost:8080 # 或者克隆官方项目 git clone https://github.com/sindresorhus/delay.git # npm i -g yarn cd delay && yarn i # VSCode 直接打开当前项目 # code .三. delay
(async() => { await delay1(1000); console.log('输出这句'); })();3.1.2 实现
const delay1 = (ms) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(); }, ms); }); }我们要传递结果。
(async() => { const result = await delay2(1000, { value: '我是若川' }); console.log('输出结果', result); })();我们也很容易实现如下代码。传递 value 最后作为结果返回。
const delay2 = (ms, { value } = {}) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(value); }, ms); }); }这样写,Promise 永远是成功。我们也需要失败。这时我们定义个参数 willResolve 来定义。
(async() => { try{ const result = await delay3(1000, { value: '我是若川', willResolve: false }); console.log('永远不会输出这句'); } catch(err){ console.log('输出结果', err); } })();3.3.2 实现
// 堆代码 duidaima.com const delay3 = (ms, {value, willResolve} = {}) => { return new Promise((resolve, reject) => { setTimeout(() => { if(willResolve){ resolve(value); } else{ reject(value); } }, ms); }); }3.4 第四版 一定时间范围内随机获得结果
(async() => { try{ const result = await delay4.reject(1000, { value: '我是若川', willResolve: false }); console.log('永远不会输出这句'); } catch(err){ console.log('输出结果', err); } const result2 = await delay4.range(10, 20000, { value: '我是若川,range' }); console.log('输出结果', result2); })();3.4.2 实现
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum); const createDelay = ({willResolve}) => (ms, {value} = {}) => { return new Promise((relove, reject) => { setTimeout(() => { if(willResolve){ relove(value); } else{ reject(value); } }, ms); }); } const createWithTimers = () => { const delay = createDelay({willResolve: true}); delay.reject = createDelay({willResolve: false}); delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options); return delay; } const delay4 = createWithTimers();实现到这里,相对比较完善了。但我们可能有需要提前结束。
(async () => { const delayedPromise = delay5(1000, {value: '我是若川'}); setTimeout(() => { delayedPromise.clear(); }, 300); // 300 milliseconds later console.log(await delayedPromise); //=> '我是若川' })();3.5.2 实现
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum); const createDelay = ({willResolve}) => (ms, {value} = {}) => { let timeoutId; let settle; const delayPromise = new Promise((resolve, reject) => { settle = () => { if(willResolve){ resolve(value); } else{ reject(value); } } timeoutId = setTimeout(settle, ms); }); delayPromise.clear = () => { clearTimeout(timeoutId); timeoutId = null; settle(); }; return delayPromise; } const createWithTimers = () => { const delay = createDelay({willResolve: true}); delay.reject = createDelay({willResolve: false}); delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options); return delay; } const delay5 = createWithTimers();3.6 第六版 取消功能
caniuse AbortController[4] npm abort-controller[5] mdn AbortController[6] fetch-abort[7] fetch#aborting-requests[8] yet-another-abortcontroller-polyfill[9]3.6.1 使用
(async () => { const abortController = new AbortController(); setTimeout(() => { abortController.abort(); }, 500); try { await delay6(1000, {signal: abortController.signal}); } catch (error) { // 500 milliseconds later console.log(error.name) //=> 'AbortError' } })();3.6.2 实现
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum); const createAbortError = () => { const error = new Error('Delay aborted'); error.name = 'AbortError'; return error; }; const createDelay = ({willResolve}) => (ms, {value, signal} = {}) => { if (signal && signal.aborted) { return Promise.reject(createAbortError()); } let timeoutId; let settle; let rejectFn; const signalListener = () => { clearTimeout(timeoutId); rejectFn(createAbortError()); } const cleanup = () => { if (signal) { signal.removeEventListener('abort', signalListener); } }; const delayPromise = new Promise((resolve, reject) => { settle = () => { cleanup(); if (willResolve) { resolve(value); } else { reject(value); } }; rejectFn = reject; timeoutId = setTimeout(settle, ms); }); if (signal) { signal.addEventListener('abort', signalListener, {once: true}); } delayPromise.clear = () => { clearTimeout(timeoutId); timeoutId = null; settle(); }; return delayPromise; } const createWithTimers = () => { const delay = createDelay({willResolve: true}); delay.reject = createDelay({willResolve: false}); delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options); return delay; } const delay6 = createWithTimers();3.7 第七版 自定义 clearTimeout 和 setTimeout 函数
const customDelay = delay7.createWithTimers({clearTimeout, setTimeout}); (async() => { const result = await customDelay(100, {value: '我是若川'}); // Executed after 100 milliseconds console.log(result); //=> '我是若川' })();3.7.2 实现
const randomInteger = (minimum, maximum) => Math.floor((Math.random() * (maximum - minimum + 1)) + minimum); const createAbortError = () => { const error = new Error('Delay aborted'); error.name = 'AbortError'; return error; }; const createDelay = ({clearTimeout: defaultClear, setTimeout: set, willResolve}) => (ms, {value, signal} = {}) => { if (signal && signal.aborted) { return Promise.reject(createAbortError()); } let timeoutId; let settle; let rejectFn; const clear = defaultClear || clearTimeout; const signalListener = () => { clear(timeoutId); rejectFn(createAbortError()); } const cleanup = () => { if (signal) { signal.removeEventListener('abort', signalListener); } }; const delayPromise = new Promise((resolve, reject) => { settle = () => { cleanup(); if (willResolve) { resolve(value); } else { reject(value); } }; rejectFn = reject; timeoutId = (set || setTimeout)(settle, ms); }); if (signal) { signal.addEventListener('abort', signalListener, {once: true}); } delayPromise.clear = () => { clear(timeoutId); timeoutId = null; settle(); }; return delayPromise; } const createWithTimers = clearAndSet => { const delay = createDelay({...clearAndSet, willResolve: true}); delay.reject = createDelay({...clearAndSet, willResolve: false}); delay.range = (minimum, maximum, options) => delay(randomInteger(minimum, maximum), options); return delay; } const delay7 = createWithTimers(); delay7.createWithTimers = createWithTimers;四. axios 取消请求
# 推荐克隆我的项目,保证与文章同步 git clone https://github.com/lxchuan12/delay-analysis.git cd delay-analysis # 我写的例子都在 examples 这个文件夹中,可以启动服务本地查看调试 npx http-server examples # 打开 http://localhost:8080