JavaScript 同步异步机制和 Promise 原理实现笔记

张开发
2026/4/10 12:28:49 15 分钟阅读

分享文章

JavaScript 同步异步机制和 Promise 原理实现笔记
题目描述如何实现一个函数对象满足给出的含异步操作且严格限制调用顺序的链式函数调用过程?arrange('aaa').wait(5).do('commit').waitFirst(3).execute();// wait 和 waitFirst 是异步操作// 要求输出为:start - output `wait 5s` - output `commit` - output 'wait 3s' - output 'aaa'思路为了实现严格限制调用顺序的链式异步操作,核心思想是将“定义执行流程”与“实际执行”分离。arrange('aaa')返回一个对象,该对象提供wait、waitFirst、do、execute等方法,每个方法都返回同一个实例以支持链式调用。关键在于理解wait(5).do('commit')这一写法:调用wait(5)时并不立即等待,而是向内部维护的任务队列中注册一个“延迟 5 秒”的异步任务,并立即返回当前对象,因此紧接着可以调用do('commit')再注册一个“输出 commit”的任务。也就是说,所有方法调用只是在“编排任务队列”,并不会阻塞后续方法的调用。只有最后调用execute()时,才会真正按顺序遍历队列,依次执行每个任务(异步任务会等待完成再执行下一个)。通过这种方式,调用顺序决定了任务在队列中的排列顺序,而执行顺序则由execute统一控制。对于异步等待(如wait和waitFirst),可以利用 Promise 实现,每个任务返回一个 Promise,在execute中通过async/await或reduce串联执行。同时,通过闭包捕获arrange的参数(如'aaa'),在队列执行完毕后输出该参数。这样既保证了链式调用的灵活性,又确保了异步操作的严格顺序。代码v1functionarrange(value){constqueue=[];return{wait(delay){queue.push(()={console.log(`wait${delay}s`);});// 注册同步函数queue.push(async()={// 注册异步函数awaitnewPromise((resolve)={setTimeout(()={resolve(true);},delay*1000);});});return{// 返回对象控制函数执行顺序do(name){queue.push(()={console.log(name);});// 注册同步函数return{waitFirst(delay2){queue.push(()={console.log(`wait${delay2}s`);});// 注册同步函数queue.push(async()={// 注册异步函数awaitnewPromise((resolve)={setTimeout(()={resolve(true);},delay2*1000);});});return{asyncexecute(){for(constfnofqueue){awaitfn();}console.log(value);}}},};},};},};}// testarrange('aaa').wait(5).do('commit').waitFirst(3).execute();思考代码V1版本通过嵌套返回对象控制链式调用顺序,存在层级冗余、扩展不便的问题;可先基于状态模式将嵌套的方法定义扁平化,通过状态机显式管控调用顺序(替代隐式的嵌套约束),再借助迭代器模式封装任务队列的执行逻辑,解耦“链式规则控制”与“任务执行”,实现代码简化与扩展能力提升。代码v2classTaskIterator{constructor(){this.tasks=[];// 任务队列}addTask(task){this.tasks.push(task);}asynciterate(){for(consttaskofthis.tasks){awaittask();}}}functionarrange(value){// 状态机:控制调用顺序(初始→wait→do→waitFirst)constSTATUS={START:0,WAIT_CALLED:1,DO_CALLED:2,WAIT_FIRST_CALLED:3,};letcurStatus=STATUS.START;constiterator=newTaskIterator();// 扁平化定义,无嵌套,方便扩展constapi={wait(delay){if(curStatus!==STATUS.START){thrownewError("Invalid order: wait must be called first!");}// 注册 wait 任务iterator.addTask(()=console.log(`wait${delay}s`));iterator.addTask(async()={awaitnewPromise((resolve)=setTimeout(resolve,delay*1000)

更多文章