了解回调
Understanding Call backs
我创建了一个小脚本来更好地理解回调。
从下面的脚本中,我预期的行为是:"http.get runs and takes on average 200 ms. The for loop "i" 增量平均需要 2500 毫秒。在 200 毫秒时,进程应该退出并且脚本应该停止工作。为什么会这样打印所有 i?如果我能更好地理解这一点,我想我就理解回调了。
var http = require("http");
var starttime = new Date();
//Function with Callback
for (var j =0; j<10; j++){
http.get({host : 'nba.com'}, function(res){
console.log("Time Taken = ", new Date() - starttime, 'ms');
process.exit();
}).on('error', function(er){
console.log('Got Error :', er.message);
})
}
//Loop that exceeds callback trigger time
for(var i=1; i<10000; i++){
console.log(i);
}
console.log("Time Taken = ", new Date() - starttime, 'ms');
node.js 中的 Javascript 是单线程的,I/O 是使用事件队列的事件驱动。因此,表示 http 请求完成的异步回调不能 运行,直到 Javascript 的原始线程完成并且 returns 控制权回到系统,然后它可以从中提取下一个事件为完成 http 请求提供服务的事件队列。
因此,您的 for
循环将 运行 在处理任何 HTTP 响应之前完成。
这是分步过程:
- 您的第一个
for
循环 运行 并发送 10 个 http 请求。
- 这些 http 请求 运行 在后台使用异步网络。当其中一个完成并有响应时,http 模块会将一个事件放入 Javascript 事件队列中,JS 解释器的工作是在完成其他活动时从事件队列中拉出该事件.
- 你的第二个
for
循环 运行s 完成,所有 i
值都输出到控制台。
- 您的脚本完成。
- 然后 JS 解释器检查事件队列以查看是否有任何未决事件。在这种情况下,会有一些http响应事件。 JS 解释器从事件队列中提取最旧的事件并调用与之关联的回调。
- 当该回调完成时,下一个事件将从事件队列中拉出并继续该过程,直到事件队列为空。
- 如果您的任何回调调用
process.exit()
,那么这会使剩余的回调短路并立即退出进程。
虽然这个其他答案是为浏览器编写的,但事件驱动的单线程概念与 node.js 中的相同,所以这个其他答案可能会为您解释更多内容:How does JavaScript handle AJAX responses in the background?
我创建了一个小脚本来更好地理解回调。
从下面的脚本中,我预期的行为是:"http.get runs and takes on average 200 ms. The for loop "i" 增量平均需要 2500 毫秒。在 200 毫秒时,进程应该退出并且脚本应该停止工作。为什么会这样打印所有 i?如果我能更好地理解这一点,我想我就理解回调了。
var http = require("http");
var starttime = new Date();
//Function with Callback
for (var j =0; j<10; j++){
http.get({host : 'nba.com'}, function(res){
console.log("Time Taken = ", new Date() - starttime, 'ms');
process.exit();
}).on('error', function(er){
console.log('Got Error :', er.message);
})
}
//Loop that exceeds callback trigger time
for(var i=1; i<10000; i++){
console.log(i);
}
console.log("Time Taken = ", new Date() - starttime, 'ms');
Javascript 是单线程的,I/O 是使用事件队列的事件驱动。因此,表示 http 请求完成的异步回调不能 运行,直到 Javascript 的原始线程完成并且 returns 控制权回到系统,然后它可以从中提取下一个事件为完成 http 请求提供服务的事件队列。
因此,您的 for
循环将 运行 在处理任何 HTTP 响应之前完成。
这是分步过程:
- 您的第一个
for
循环 运行 并发送 10 个 http 请求。 - 这些 http 请求 运行 在后台使用异步网络。当其中一个完成并有响应时,http 模块会将一个事件放入 Javascript 事件队列中,JS 解释器的工作是在完成其他活动时从事件队列中拉出该事件.
- 你的第二个
for
循环 运行s 完成,所有i
值都输出到控制台。 - 您的脚本完成。
- 然后 JS 解释器检查事件队列以查看是否有任何未决事件。在这种情况下,会有一些http响应事件。 JS 解释器从事件队列中提取最旧的事件并调用与之关联的回调。
- 当该回调完成时,下一个事件将从事件队列中拉出并继续该过程,直到事件队列为空。
- 如果您的任何回调调用
process.exit()
,那么这会使剩余的回调短路并立即退出进程。
虽然这个其他答案是为浏览器编写的,但事件驱动的单线程概念与 node.js 中的相同,所以这个其他答案可能会为您解释更多内容:How does JavaScript handle AJAX responses in the background?