同事为难我:如何巧妙应对Promise的应用难题?
背景
背景是这样的,前同事给我出了一个难题,原因是他在最近找工作面试中被问到关于 Promise 相关的问题,单独我们看问题,我们其实每个任务都可以简单地做出来,但是需要组合考虑整体的步骤,和实际问题考我们的核心内容是什么?我很困惑顺便复习一下对 Promise 的理解
问题
实现一个简易的序列操作,支持sleep, log, exec 三类操作 sleep:支持等待ms秒之后再执行下一个操作, log:支持同步打印一些信息, exec:支持传一个函数,函数都是异步(即返回一个Promise),当异步函数执行完成之后,才能继续下一个 用 js 实现。
拆分问题
要实现一个支持 sleep、log 和 exec 三类操作的序列操作系统,可以创建一个操作队列,并依次执行队列中的操作。以下是一个基于 JavaScript 的实现:
想到操作队列自然是数组,里面管理多个 Promise 对象
Sleep
顾名思义,我们是将接收到一个参数,然后往执行某件事。参数是 ms 一般我们用毫秒做时间的单位,为了在setTimeout 这类方法中使用的时候,是单位一致的,那么我可以构思代码
function sleep(ms) {
queue.push(() => new Promise(resolve => setTimeout(resolve, ms)));
}
sleep(ms)方法接受一个毫秒数ms,返回一个新的Promise,该 Promise 在ms毫秒后解决。- 使用
setTimeout实现等待功能。
log
打印方法,其实很简单,我只需要接收,一个需要打印的参数,message。然后输出就好了,最后返回一个已经解决的 Promise,我们需要有一个 Promise 队列概念
function log(message) {
queue.push(() => {
console.log(message);
return Promise.resolve(); // 返回一个已经解决的Promise
});
}
log(message)方法接受一个字符串message,在控制台输出该信息。- 返回一个已经解决的
Promise。
exec
接收一个异步函数作为参数,然后放到队列当中
function exec(asyncFunc) {
queue.push(async () => {
await asyncFunc();
});
}
}
exec(asyncFunc)方法接受一个返回Promise的异步函数asyncFunc,将其添加到队列中。
依次执行队列中全部的任务
function run() {
for (const task of queue) {
await task();
}
}
run()方法异步地按顺序执行队列中的每个任务。- 使用
for...of循环和await保证任务按顺序执行。
我们需要整理一下代码,将全部的方法都返回 this, 方便可以使用链式调用, 最后我们加上示例就完成了
最后结果
class Sequence {
constructor() {
this.queue = [];
this.currentPromise = Promise.resolve();
}
sleep(ms) {
this.queue.push(() => new Promise(resolve => setTimeout(resolve, ms)));
return this;
}
log(message) {
this.queue.push(() => {
console.log(message);
return Promise.resolve();
});
return this;
}
exec(asyncFunc) {
this.queue.push(async () => {
await asyncFunc();
});
return this;
}
async run() {
for (const task of this.queue) {
await task();
}
}
}
// 示例使用
const sequence = new Sequence();
sequence
.sleep(1000) // 等待 1 秒
.log("This is a log message.") // 打印日志
.exec(() => new Promise(resolve => {
setTimeout(() => {
console.log("Async function executed after 2 seconds.");
resolve();
}, 2000);
})) // 执行异步函数
.log("Sequence completed.") // 打印日志
.run(); // 运行队列
总结内容
Sequence类:这是一个用于管理操作队列的类。它包含一个队列(this.queue)来存储所有操作,以及一个currentPromise用于跟踪当前的 Promise 链。sleep(ms)方法:将一个返回 Promise 的函数推入队列,该函数在等待指定的毫秒数后解析。log(message)方法:将一个同步日志操作推入队列,并返回一个立即解析的 Promise。exec(asyncFunc)方法:将一个异步函数推入队列,该函数返回一个 Promise,确保在函数完成后才继续下一个操作。run()方法:遍历队列中的所有操作,并确保它们按顺序执行。每个操作会等待前一个操作完成(通过await)后再开始执行。
最后祝大家周末愉快,有一个美好的周末时光!!
转载自:https://juejin.cn/post/7372396200861646898