使用回调函数按调用顺序在控制台打印数字的实现疑问
按调用顺序输出异步数字的实现方案
问题背景
作为JavaScript新手,需要实现一个功能:调用getAsyncNumber函数传入0-4时,数字能严格按照调用顺序在控制台输出。给定的起始代码中,asynchronousResponse会随机延迟后执行回调,直接调用的话输出顺序会混乱,且要求使用函数外部的变量存储相关状态。
起始代码如下:
function asynchronousResponse(value, callback) { var delay = Math.floor(Math.random() * 10) * 1000; setTimeout(() => callback(value), delay); } function getAsyncNumber(number) { /* Add implementation of getAsyncNumber function in a way that numbers appear on a console in order in which they have been called. Use asynchronousResponse to generate this responses. */ } getAsyncNumber(0); getAsyncNumber(1); getAsyncNumber(2); getAsyncNumber(3); getAsyncNumber(4);
实现思路
核心是让异步任务按顺序排队执行:
- 用外部变量维护一个任务队列,按
getAsyncNumber的调用顺序存储每个数字对应的异步任务。 - 用另一个外部变量标记当前是否有任务在执行,避免同时启动多个任务。
- 每次添加任务后,检查是否可以启动队列处理;当前任务执行完成(输出数字)后,自动触发下一个任务的执行。
回调风格的实现代码
// 外部变量:存储待执行的异步任务队列 const taskQueue = []; // 外部变量:标记当前是否有异步任务在执行 let isProcessing = false; function asynchronousResponse(value, callback) { var delay = Math.floor(Math.random() * 10) * 1000; setTimeout(() => callback(value), delay); } function getAsyncNumber(number) { // 将当前数字的异步逻辑包装成任务加入队列 taskQueue.push((next) => { asynchronousResponse(number, (value) => { console.log(value); // 当前任务完成,调用next触发下一个任务 next(); }); }); // 如果当前没有任务在执行,启动队列处理 if (!isProcessing) { processNextTask(); } } // 处理队列中的下一个任务 function processNextTask() { // 队列为空时,标记为未处理状态并返回 if (taskQueue.length === 0) { isProcessing = false; return; } isProcessing = true; // 取出队列第一个任务执行,传入processNextTask作为完成后的回调 const currentTask = taskQueue.shift(); currentTask(processNextTask); } // 按顺序调用 getAsyncNumber(0); getAsyncNumber(1); getAsyncNumber(2); getAsyncNumber(3); getAsyncNumber(4);
代码解释
taskQueue:每个元素是一个函数,封装了对应数字的asynchronousResponse调用和输出逻辑,同时接收一个next参数用于触发下一个任务。isProcessing:确保同一时间只有一个异步任务在执行,防止队列被重复启动。processNextTask:负责从队列头部取出任务执行,当前任务完成后(即asynchronousResponse的回调触发并输出数字),会递归调用自身处理下一个任务,以此保证严格的调用顺序。
内容的提问来源于stack exchange,提问作者JKukielski
相关产品推荐
相关产品推荐

