简体   繁体   English

Q承诺链错误后存在承诺链

[英]Q promise chain exists promise chain after error

I have a node.js script that opens up a Azure container, takes screenshots of a page across multiple different countries while streaming them to the Azure container. 我有一个node.js脚本,该脚本打开一个Azure容器,在将它们流式传输到Azure容器的同时拍摄多个国家/地区的页面的屏幕截图。 The issue I'm having is if I encounter an error in the streaming process, it finishes the remaining screenshots for that given id and then exits out of the promise chain. 我遇到的问题是,如果我在流传输过程中遇到错误,它将完成给定ID的其余屏幕截图,然后退出承诺链。

So if I encounter an error at Id 211006 , it completes taking all the screenshots, and then exits the stream. 因此,如果我在ID 211006遇到错误,它将完成所有屏幕截图的获取,然后退出流。 It doesn't continue on. 它不会继续下去。

I'm very new to how promises work and how they catch errors, but my understanding is that if, say, 211006 does encounter an error, the script would complete the promise chain, and then show me any error prior to running .fin - that's not the case. 我对211006工作方式以及它们如何捕获错误是非常211006 ,但是我的理解是,例如211006确实遇到错误,脚本将完成211006链,然后在运行.fin之前向我显示任何错误-事实并非如此。

Can anybody help? 有人可以帮忙吗?

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();

A chain of promises is stopped anytime an error is allowed back into the chain. 只要允许错误返回链中,诺言链就会停止。 That sets the promise state to rejected and will call the next error handler in any subsequent .then() handlers, not the fulfilled handler. 这会将promise状态设置为拒绝,并将在任何后续的.then()处理程序中调用下一个错误处理程序,而不是完成的处理程序。

If you want the chain to continue, then you need to catch the error. 如果希望链继续,则需要捕获错误。 Catching the error will cause the promise infrastructure to consider it "handled" and the promise state will again be fulfilled and it will continue executing fulfilled handlers. 捕获错误将使Promise基础结构将其视为“已处理”,并且Promise状态将再次被实现,并且它将继续执行已实现的处理程序。

Promise errors are analogous to exceptions. 承诺错误类似于异常。 If they are not handled, they will abort processing up until the first exception handler. 如果未处理它们,它们将中止处理,直到第一个异常处理程序为止。 If they are handled with an exception handler, then processing will continue normally after that exception handler. 如果使用异常处理程序处理它们,则处理将在该异常处理程序之后正常继续。

In your specific case, if you want the chaing to continue, you will need to handle errors in each of these types of lines: 在特定情况下,如果您希望继续进行跟踪,则需要处理以下每种类型的行中的错误:

return ScreenshotService.getAllCountriesOfId('308572');

You can do that like this: 您可以这样做:

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

Since you have a lot of repeated code, you should probably change your code into something that iterates through an array of country IDs rather than just copy lines of code over and over. 由于您有很多重复的代码,因此您可能应该将代码更改为可通过一系列国家/地区ID进行迭代的内容,而不是一遍又一遍地复制代码行。


Here's a means of using .reduce() to chain all the promises in a loop and get rid of so much repetitive code and handle individual country errors so the chain continues: 这是一种使用.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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM