Promise 链和错误处理

Promise chaining and error handling

我正在尝试理解使用 promises 的链接和错误处理。在这里,我有一些承诺。

return ad_fetcher.getAds(live_rail_url, ad_time, req.sessionID)
        .spread(generator.playlist_manipulate) // returns Promise.resolve([data, anotherData])
        .then(client.incrAsync(config.channel_name + ":ad_hits", "vdvd")) // FOCUS HERE
        .then(function() {
            console.log("AD FETCHED AND PLAYLIST GENERATED.");
            res.send(generator.generate_regular(config.default_bitrate));
            })
        .catch(function(err) {
            console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
            console.log("!!! AD FETCHER - THERE WAS AN ERROR:!!!!!!!!!!!");
            client.sadd(config.channel_name + ":ad_errors", err);
            client.incr(config.channel_name + ":ad_errors:count");
            console.log(err);
            console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
            res.send(generator.generate_regular(config.default_bitrate));
    });

现在在 client.incrAsync(config.channel_name + ":ad_hits", "vdvd") 行,我故意写错了语法,看看错误是否被 .catch 捕获。但是当我 运行 这个时,我得到这个:

Unhandled rejection Error: ERR wrong number of arguments for 'incr' command

但是当我将该承诺的用法更改为:

.
.
    .then(function() {
        return client.incrAsync(config.channel_name + ":ad_hits", "vdvd");
    })
.
.

错误抓得很好。已经不是"unhandled"了。

我不明白这种行为。 incrAsync return 不是一个承诺,所以它的错误应该被链末端的 .catch 捕获吗?

注意:我承诺了redis客户端,毫无疑问。

谢谢!

当您链接承诺时,您会使用前一个函数的结果调用链中的下一个函数。

但是,您正在调用 returns 直接承诺的函数。因此,除非 调用 该函数 returns 一个 returns Promise 的函数,否则您没有正确链接。

所以这些中的任何一个都可以工作:

.spread(generator.playlist_manipulate) // returns Promise.resolve([data, anotherData])
.then(client.incrAsync) // this function will receive [data, anotherData]

或者,正如您在问题中使用的那样,匿名函数:

.spread(generator.playlist_manipulate) // returns Promise.resolve([data, anotherData])
.then(function() { // this function receives [data, anotherData] but throws it away
    // this Promise is "subsumed" by the Promise chain. The outer Promise BECOMES this Promise
    return client.incrAsync(config.channel_name + ":ad_hits", "vdvd");
})

否则,你写的基本上是这样的:

.then(function)
.then(Promise)
.then(function)

但是如果您希望函数在最后由 .catch 块处理,则需要将函数传递给 .then,而不是 Promises。