Javascript 在回调函数中调用异步函数

Javascript 在回调函数中调用异步函数,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我在理解异步函数时遇到了一些问题。我已经读了中的那一章,但我仍然不能理解它 基本上,我想请求一个ressource(使用节点包cheerio),解析它以获得有效的URL,并将每个匹配项添加到我的redis集合setname 问题是,最终它只是将第一个匹配项添加到redis集合 function parse(url, setname) { request(url, function (error, response, body) { if (!error &am

我在理解异步函数时遇到了一些问题。我已经读了中的那一章,但我仍然不能理解它

基本上,我想请求一个ressource(使用节点包
cheerio
),解析它以获得有效的URL,并将每个匹配项添加到我的redis集合
setname

问题是,最终它只是将第一个匹配项添加到redis集合

function parse(url, setname) 
{
    request(url, function (error, response, body) 
    {
        if (!error && response.statusCode == 200) 
        {
            $ = cheerio.load(body)

            // For every 'a' tag in the body
            $('a').each(function() 
            {
                // Add blog URL to redis if not already there.
                var blog = $(this).attr('href')
                console.log("test [all]: " + blog);

                // filter valid URLs
                var regex = /http:\/\/[^www]*.example.com\//
                var result = blog.match(regex);
                if(result != null) 
                {
                    console.log("test [filtered]: " + result[0]);

                    redis.sismember(setname, result[0], function(err, reply) 
                    {
                        if(!reply) 
                        {
                            redis.sadd(setname, result[0])
                            console.log("Added " + result[0])
                        }
                        redis.quit()    
                    })
                }
            })
        }
    })
}
我非常感谢有人给我指点,告诉我如何重新构造它,这样redis.sadd方法才能得到正确的结果

当前实现的输出如下所示:

test [all]: http://test1.example.com/
test [filtered]: http://test1.example.com/
...
Added http://test2.example.com/
因此,它添加了test1.example.com,但没有打印“添加”行,也没有添加test2.example.com,而是打印“添加”行


谢谢大家!

第一个问题是由
redis.sismember()
异步引起的:调用其回调时,您已经覆盖了
result
变量,因此它将指向它拥有的最后一个值,而不是调用
redis.sismember()时的值

解决此问题的一种方法是通过将异步函数包装到闭包中来创建新的作用域变量:

(function(result) {
  redis.sismember(setname, result[0], function(err, reply) {
    ...
  });
})(result);
另一个选项是创建用作回调的分部函数:

  redis.sismember(setname, result[0], function(result, err, reply) {
    ...
  }.bind(this, result));

我认为,第二个问题是由于调用了
redis.quit()
,在第一个
sadd()
之后关闭了redis连接。您没有检查
err
,但如果您这样做,可能会告诉您更多信息。

谢谢,我添加了闭包,并将
redis.quit()
移动到解析函数的末尾,现在一切正常。