简体   繁体   中英

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. 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.

So if I encounter an error at Id 211006 , it completes taking all the screenshots, and then exits the stream. 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.

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.

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 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.


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:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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