likes
comments
collection
share

同事为难我:如何巧妙应对Promise的应用难题?

作者站长头像
站长
· 阅读数 18

背景

背景是这样的,前同事给我出了一个难题,原因是他在最近找工作面试中被问到关于 Promise 相关的问题,单独我们看问题,我们其实每个任务都可以简单地做出来,但是需要组合考虑整体的步骤,和实际问题考我们的核心内容是什么?我很困惑顺便复习一下对 Promise 的理解

问题

实现一个简易的序列操作,支持sleep, log, exec 三类操作 sleep:支持等待ms秒之后再执行下一个操作, log:支持同步打印一些信息, exec:支持传一个函数,函数都是异步(即返回一个Promise),当异步函数执行完成之后,才能继续下一个 用 js 实现。

拆分问题

要实现一个支持 sleeplogexec 三类操作的序列操作系统,可以创建一个操作队列,并依次执行队列中的操作。以下是一个基于 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();  // 运行队列

总结内容

  1. Sequence:这是一个用于管理操作队列的类。它包含一个队列(this.queue)来存储所有操作,以及一个 currentPromise 用于跟踪当前的 Promise 链。
  2. sleep(ms) 方法:将一个返回 Promise 的函数推入队列,该函数在等待指定的毫秒数后解析。
  3. log(message) 方法:将一个同步日志操作推入队列,并返回一个立即解析的 Promise。
  4. exec(asyncFunc) 方法:将一个异步函数推入队列,该函数返回一个 Promise,确保在函数完成后才继续下一个操作。
  5. run() 方法:遍历队列中的所有操作,并确保它们按顺序执行。每个操作会等待前一个操作完成(通过 await)后再开始执行。

最后祝大家周末愉快,有一个美好的周末时光!!

转载自:https://juejin.cn/post/7372396200861646898
评论
请登录