javascript - 在回调中调用异步函数

标签 javascript node.js asynchronous

我在理解异步函数时遇到了一些困难。我已阅读 Mixu's Node Book 中的章节但我仍然无法理解它。

基本上我想请求一个资源(使用 Node 包 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,但如果您这样做,它可能会告诉您更多信息。

关于javascript - 在回调中调用异步函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16628483/

相关文章:

javascript - Angular js 在返回之前等待数据

c# - 涉及异步调用时如何跟踪工作单元?

javascript - 文本字段中的描述文本?

javascript - moment.js 中的 isValid() 和 _isValid 有什么区别?

javascript - Node.js:无法从 array.map() 返回新数组

javascript - 抛出新的 TypeError ('callback provided to sync glob' )?

javascript - 可以在 .env 文件 Node js 中发送参数

javascript - 如何在 JavaScript 中创建对象列表

javascript - javascript 表单中 grabFormSelects() 的用途是什么?

javascript - 如何在第二个ajax调用之外获取值