在前端开发中,经常需要处理异步任务的结果,例如从服务器请求数据或者等待用户输入。为了让代码更加清晰、简洁,我们可以使用 JavaScript 中的 Promise 和 async/await 语法来处理异步任务。但是有些情况下,我们需要对多个异步任务进行协调,例如需要等待两个异步任务都完成后才能执行下一步操作。这时候,就可以使用延迟阵列(DelayQueue)来实现。
延迟阵列的基本概念
延迟阵列是一个用于管理延迟任务的队列结构。它提供了一组方法来添加和删除延迟任务,并且可以指定每个任务的延迟时间。当任务的延迟时间到达后,延迟阵列会自动执行该任务。
延迟阵列通常使用 Promise 和 setTimeout 函数来实现。每个延迟任务都对应一个 Promise 对象,Promise 对象的状态表示任务是否已完成。当延迟时间到达后,Promise 对象的状态会被设置为 resolved,并且会执行对应的回调函数。
使用 when() 美元操作符
当需要对多个异步任务进行协调时,可以使用 when() 美元操作符来创建一个延迟阵列。when() 函数接受一个数组作为参数,数组中的每个元素都是一个 Promise 对象。当所有的 Promise 对象都变为 resolved 状态时,when() 函数返回一个新的 Promise 对象,表示所有任务已经完成。
const task1 = new Promise(resolve => setTimeout(resolve, 1000)); const task2 = new Promise(resolve => setTimeout(resolve, 2000)); when([task1, task2]).then(() => { console.log('All tasks are completed!'); });
在上面的例子中,我们创建了两个延迟任务,分别延迟 1 秒和 2 秒。当这两个任务都完成后,控制台将输出 'All tasks are completed!'。
深入理解 when() 美元操作符
除了可以用于等待多个异步任务的完成外,when() 美元操作符还有一些其他的用法,例如:
应用到单个 Promise 对象
当需要对一个 Promise 对象进行处理时,也可以使用 when() 美元操作符来封装它。这样可以让代码结构更加统一。
const task = new Promise(resolve => setTimeout(resolve, 1000)); when(task).then(() => { console.log('Task is completed!'); });
处理异常情况
当延迟任务执行过程中发生错误时,Promise 对象的状态会变为 rejected,并且会执行对应的 catch() 回调函数。但是如果使用 when() 美元操作符来等待多个任务的完成,其中任何一个任务出错都会导致整个链路失败。为了避免这种情况,我们可以使用 Promise.allSettled() 函数来处理异常情况。
const task1 = new Promise(resolve => setTimeout(resolve, 1000)); const task2 = new Promise((resolve, reject) => setTimeout(reject, 2000)); when([task1, task2]).then(() => { console.log('All tasks are completed!'); }).catch(reason => { console.error(reason); });
在上面的例子中,我们故意将第二个任务设置为 rejected 状态。当延迟阵列中的任何一个 Promise 对象状态变为 rejected 时,catch() 回调函数就会被执行。如果需要继续等待其他任务的完成,可以在 catch() 回调函数中返回一个新的 Promise 对象。
处理超时
有些情况下,我们需要限制任务的执行时间。当任务的执行时间超过规定的时间后,我们可以将任务的 Promise
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/8317