【问题标题】:Chaining promises链接承诺
【发布时间】:2014-06-19 08:31:32
【问题描述】:

我想要实现的是解析给定网站并将其标题写入titles.txt。我使用request 模块获取网站,使用cheerio 获取标题。

我正在使用Q 模块来创建以下两个承诺:

读取标题

var readTitle = function(url) {
    var deferred = Q.defer();
    request({
        url: url
    }, function(err, response, body) {
        var $ = cheerio.load(body);
        deferred.resolve($("title").text());
    });
    return deferred.promise;
};

写标题

var writeTitle = function(title) {
    var deferred = Q.defer();
    fs.appendFile('titles.txt', title + "\n", function() {
        deferred.resolve();
    });
    return deferred.promise;
};

我希望以下脚本将GoogleStack Overflow 写入文本文件:

readTitle('http://www.google.com')
.then(writeTitle)
.then(readTitle('http://www.stackoverflow.com'))
.then(writeTitle);

但我实际得到的是:

Google
undefined

我做错了什么?

【问题讨论】:

  • 只是猜测:.then(readTitle('http://www.stackoverflow.com').then(writeTitle));.
  • @bloodyKnuckles:谢谢,这行得通,但为什么呢? :)
  • 您应该将函数引用(尚未调用的函数)传递给.then(),而不是已执行的函数。因此,如果您的函数需要参数,请像这样传递它:.then(function() {return readTitle('http://www.stackoverflow.com')})
  • 这段代码可以简单得多,你会接受 Bluebird 承诺的解决方案吗?
  • 接受的答案没有提供您在问题中的行为。相反,它同时触发了两个 Promise。 RobertLevy 的回答更正确。您可以使用绑定缩短它。另外值得一提的是,您的手动承诺可以消除错误。

标签: node.js promise q


【解决方案1】:

then 需要传递一个函数而不是一个值

.then(function() {return readTitle('http://www.stackoverflow.com'); })
.then(writeTitle);

【讨论】:

  • 这个答案实际上是目前唯一正确的答案,如果性能无关紧要,第一个.then 可以写成.then(readTitle.bind(null,'http://www.stackoverflow.com')) - 我假设这里就是这种情况,否则没有人无论如何都会在快速承诺库上使用 Q。
  • bloodKnuckles 是正确的。我接受了他的回答。我确实关心表现,本杰明。我猜你更喜欢蓝鸟?为什么?有没有证据表明它实际上更快?
  • @Amberlamps 仅当您考虑基准测试时 ^^ github.com/petkaantonov/bluebird/blob/master/benchmark/stats/… 它快两个数量级,有很多有用的收集方法,并且通过更好的堆栈跟踪和未处理的拒绝检测更易于调试。
  • @Amberlamps 也是,bloodKnuckles 不正确,如果您想同时触发两个请求,也有一个好方法。
猜你喜欢
  • 2015-04-15
  • 2023-01-27
  • 2015-01-21
  • 2016-01-17
  • 1970-01-01
  • 1970-01-01
  • 2018-02-15
  • 2016-06-21
  • 2017-10-01
相关资源
最近更新 更多