Q promise链存在错误后的promise链

Q promise chain exists promise chain after error

我有一个 node.js 脚本可以打开一个 Azure 容器,截取多个不同国家/地区的页面屏幕截图,同时将它们流式传输到 Azure 容器。我遇到的问题是,如果我在流式传输过程中遇到错误,它会完成该给定 ID 的剩余屏幕截图,然后退出承诺链。

因此,如果我在 Id 211006 处遇到错误,它会完成所有屏幕截图,然后退出流。它不会继续下去。

我对 promise 的工作原理和捕获错误的方式非常陌生,但我的理解是,如果 211006 确实遇到错误,脚本将完成 promise 链,然后显示运行 .fin 之前的任何错误 - 事实并非如此。

有人可以帮忙吗?

AzureService.createContainer()
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('308572');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('211006');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('131408');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('131409');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('789927');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('211007');
    })
    .then(function () {
        return ScreenshotService.getAllCountriesOfId('833116');
    })

    // Upload Log file into Azure storage
    .fin(function () {
        AzureService.init({
            container: config.azure.storage.msft.CONTAINER.LOG,
            account: config.azure.storage.msft.ACCOUNT,
            key: config.azure.storage.msft.ACCESS_KEY,
            file: config.file.log,
            isLogFile: true
        });

        log.info('Utility: Uploading log file [ %s ] to Azure storage container [ %s ]', AzureService.file, AzureService.container);

        return AzureService.uploadLocalFileToStorage()
            .then(function () {
                return util.deleteFile({fileName: AzureService.file, isLogFile: true});
            })
            .fail(function (err) {
                log.info(err);
            })
            .done();
    })

    .fail(function (err) {
        log.info(err);
    })

    .done();

只要允许错误返回链中,承诺链就会停止。这会将 promise 状态设置为 rejected,并将调用任何后续 .then() 处理程序中的下一个错误处理程序,而不是已完成的处理程序。

如果你想让链条继续下去,那么你需要捕获错误。捕获错误将导致 promise 基础设施考虑它 "handled" 并且 promise 状态将再次被履行并且它将继续执行已履行的处理程序。

Promise 错误类似于异常。如果未处理它们,它们将中止处理,直到第一个异常处理程序出现。如果使用异常处理程序处理它们,则处理将在该异常处理程序之后继续正常进行。

在您的特定情况下,如果您希望链接继续,您将需要处理以下每种类型的行中的错误:

return ScreenshotService.getAllCountriesOfId('308572');

你可以这样做:

return ScreenshotService.getAllCountriesOfId('308572').then(null, function(err) {
    console.log(err);
    // error is now handled and processing will continue
});

由于您有很多重复的代码,您可能应该将代码更改为循环访问国家/地区 ID 数组的代码,而不是一遍又一遍地复制代码行。


这是一种使用 .reduce() 将所有 promise 链接在一个循环中并摆脱如此多的重复代码并处理个别国家/地区错误的方法,以便链继续:

var countryIds = ['308572', '211006', '131408', '131409', '789927', '211007', '833116'];
countryIds.reduce(function(p, item) {
    return p.then(function() {
        return ScreenshotService.getAllCountriesOfId(item).then(null, function(err) {
            console.log(err);
        });
    });
}, AzureService.createContainer())
// Upload Log file into Azure storage
.fin(function () {
   ... rest of your code continued here