如何实现按顺序执行回调的inOrder函数:回调模式与Promise实现
嘿,这个问题的核心是要控制两个异步操作的执行顺序,不管它们的延迟有多随机对吧?首先得纠正一个小误区:你原代码里直接把setTimeout的返回值(定时器ID)传给inOrder是行不通的——一旦调用setTimeout,定时器就已经自顾自开始计时了,彼此完全独立。我们得把这两个异步操作包装成可被调度的任务,让inOrder来决定什么时候启动第二个任务。
下面分两种方式实现:
1. 回调模式实现inOrder
我们让inOrder接收两个带回调参数的函数,第一个任务执行完成后,通过回调通知inOrder,再启动第二个任务:
// 重新包装两个异步任务,让它们支持回调通知完成 function logOne(callback) { setTimeout(() => { console.log("one!"); callback(); // 任务做完了,告诉inOrder可以继续了 }, Math.random() * 1000); } function logTwo(callback) { setTimeout(() => { console.log("two!"); callback(); // 可选,根据是否需要后续通知决定 }, Math.random() * 1000); } // 回调版的inOrder函数 function inOrder(task1, task2) { // 先跑第一个任务,它完成后再跑第二个 task1(() => { task2(() => {}); }); } // 调用测试,不管延迟怎么随机,肯定先输出one!再two! inOrder(logOne, logTwo);
2. Promise模式实现inOrder
用Promise来封装异步任务会更优雅,利用then()的链式调用或者async/await来保证顺序:
基础Promise版本
// 包装成返回Promise的任务 const logOne = () => new Promise(resolve => { setTimeout(() => { console.log("one!"); resolve(); // 标记任务完成 }, Math.random() * 1000); }); const logTwo = () => new Promise(resolve => { setTimeout(() => { console.log("two!"); resolve(); }, Math.random() * 1000); }); // Promise版inOrder function inOrder(task1, task2) { // 先执行task1,完成后自动执行task2 return task1().then(task2); } // 调用测试 inOrder(logOne, logTwo);
更简洁的async/await版本
如果喜欢同步风格的写法,用async/await会更直观:
// async/await版inOrder async function inOrder(task1, task2) { await task1(); // 等第一个任务做完 await task2(); // 再做第二个任务 } // 调用方式完全一样 inOrder(logOne, logTwo);
再强调一下原写法的问题
你原代码里的logOne和logTwo是直接调用setTimeout得到的数字ID,这两个定时器在你定义变量的时候就已经开始计时了,inOrder拿到的只是两个数字,根本没法干预它们的执行顺序。所以必须把异步操作包装成待执行的函数,让inOrder来掌控启动时机。
内容的提问来源于stack exchange,提问作者Hakim Aarif
相关产品推荐
相关产品推荐

