Node.JS:如何将变量传递给异步回调? [复制]

Posted

技术标签:

【中文标题】Node.JS:如何将变量传递给异步回调? [复制]【英文标题】:Node.JS: How to pass variables to asynchronous callbacks? [duplicate] 【发布时间】:2012-10-24 16:17:10 【问题描述】:

我确定我的问题是由于对 node.js 中的异步编程缺乏了解,但这里是这样。

例如:我有一个要抓取的链接列表。当每个异步请求返回时,我想知道它用于哪个 URL。但是,大概是因为竞态条件,每个请求返回的 URL 都设置为列表中的最后一个值。

var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) 
    var url = links[link];
    require('request')(url, function() 
        console.log(url);
    );

预期输出:

http://google.com
http://yahoo.com

实际输出:

http://yahoo.com
http://yahoo.com

所以我的问题是:

    如何将 url(按值)传递给回调函数?或 链接 HTTP 请求以便它们按顺序运行的正确方法是什么?或 我还缺少什么?

PS:对于 1. 我不想要一个检查回调参数的解决方案,而是一种通用的回调方法,它知道“从上面”的变量。

【问题讨论】:

【参考方案1】:

您的 url 变量的范围不限于 for 循环,因为 javascript 仅支持全局和函数范围。因此,您需要为您的 request 调用创建一个函数范围,以使用立即函数在循环的每次迭代中捕获 url 值:

var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) 
    (function(url) 
        require('request')(url, function() 
            console.log(url);
        );
    )(links[link]);

顺便说一句,在循环中间嵌入 require 不是一个好习惯。它可能应该重写为:

var request = require('request');
var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) 
    (function(url) 
        request(url, function() 
            console.log(url);
        );
    )(links[link]);

【讨论】:

这与范围无关。这是关于闭包的。许多其他语言没有块作用域,但由于缺少闭包而没有遇到这个问题。 关键是,如果 JavaScript 确实支持块作用域,那么在 OP 代码的回调函数中对 url 的闭包访问将起作用,因为循环的每次迭代都会得到自己的 url变量(如在 C# 中)。 为简洁起见,require 就在其中,在我的代码中,所有 requires 都在开头。 如果我不在回调中使用forloop,它将返回未定义的url。【参考方案2】:

有关此问题的一般性讨论,请参阅 https://***.com/a/11747331/243639。

我会建议类似的东西

var links = ['http://google.com', 'http://yahoo.com'];

function createCallback(_url) 
    return function() 
        console.log(_url);
    
;

for (link in links) 
    var url = links[link];
    require('request')(url, createCallback(url));

【讨论】:

在 *** 上有很多更好的链接可以解释这个问题。例如:***.com/questions/3572480/…【参考方案3】:

检查此blog。可以使用 .bind() 方法传递变量。在你的情况下,它会是这样的:

var links = ['http://google.com', 'http://yahoo.com'];
for (link in links) 
var url = links[link];

require('request')(url, function() 

    console.log(this.urlAsy);

.bind(urlAsy:url));

【讨论】:

我更喜欢这种方法,因为它比在函数中包装东西更简洁。 这个不用forloop也能工作!

以上是关于Node.JS:如何将变量传递给异步回调? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

Node.js如何将数组索引传递给异步函数

如何识别回调是同步执行还是异步执行? [复制]

如何识别回调是同步执行还是异步执行? [复制]

Socket.io、Node.js:如何在 javascript.js 中将 javascript 变量传递给 mysql 查询?

node.js初步了解——慕课网(回调,作用域,上下文)

WPF异步回调时回调函数如何获取异步函数产生的变量