Node.js循环中函数调用输出顺序异常问题咨询
为什么你的Node.js代码输出顺序是1 2 3 oke22 oke22 oke22?
这个问题的核心是Node.js的异步非阻塞特性,我来给你拆解清楚:
首先看你的代码逻辑:
ans.map((val, indx) => { const options = { host: 'www.xxxx.com', path: '/path', port: 80, path: path, // 这里注意:重复的path属性会被后面的覆盖,大概率是笔误 method: 'GET', }; console.log(val); send.getJSON(options, (code ,result) => { console.log("oke22"); }); })
当ans是[1,2,3]时,代码的执行流程是这样的:
- 进入
map循环处理第一个元素1:console.log(val)是同步操作,会立刻输出1;- 调用
send.getJSON发起HTTP请求——这是个异步操作,Node.js不会傻等着请求完成,而是把这个请求的回调函数(就是打印oke22的那个函数)放到「事件队列」里,然后直接跳去处理下一个循环。
- 处理第二个元素
2:- 同步执行
console.log(val),立刻输出2; - 同样发起异步请求,回调被放进事件队列。
- 同步执行
- 处理第三个元素
3:- 同步执行
console.log(val),立刻输出3; - 发起异步请求,回调被放进事件队列。
- 同步执行
直到整个map循环里的所有同步代码都跑完了,Node.js才会回过头去处理事件队列里的回调函数。这时候三个HTTP请求的回调依次执行,就输出了三个oke22。
这就是为什么你看到的顺序是1 2 3 oke22 oke22 oke22,而不是1 oke22 2 oke22 3 oke22。
如果想实现「输出一个val,等请求完成输出oke22,再处理下一个val」的顺序,可以用async/await配合for...of循环(map本身不支持顺序等待异步操作):
async function processAnswers(ans) { for (const val of ans) { console.log(val); // 把send.getJSON包装成Promise,才能用await等待请求完成 await new Promise((resolve) => { const options = { host: 'www.xxxx.com', path: path, // 修正重复的path属性 port: 80, method: 'GET', }; send.getJSON(options, (code, result) => { console.log("oke22"); resolve(); // 请求完成后触发resolve,让await继续执行下一轮循环 }); }); } } // 调用函数 processAnswers([1,2,3]);
这样每次循环都会等待当前请求完成、打印完oke22后,再处理下一个元素,就能得到你想要的顺序啦。
内容的提问来源于stack exchange,提问作者xcevox
相关产品推荐
相关产品推荐

