question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Break from promise chain early

See original GitHub issue

First of all, congratulations and thank you very much for making and maintaining this library, its been extremely helpful!

I have a chain of promises at certain stages I would like the whole chain to fail but I have catch handlers further on which I would like to ignore. My use case is a file comparison after it has been processed, I do this for all files in a directory.

readdirp({ root: 'data' }).on('data', (entry) => {
    let promise = renderer.execute(entry.fullPath, "chrome");
    promise.then((file) => {
        return Q.nfcall(fs.writeFile, "./result/chrome-"+entry.name, file);
    }).catch((err) => {
        console.error("Failed saving file","./result/chrome-"+entry.name,"skipping comparison.");
        //Break from chain here
    }).then(() =>{
        return renderer.execute(entry.fullPath,"phantom");
    }).catch((err)=>{
        console.error("phantom renderer failed", err);
        //break from chain
    }).then((file)=>{
        return Q.nfcall(fs.writeFile, "./result/phantom-"+entry.name, file);
    }).catch((err) => {
        console.error("Failed saving file","./result/phantom-"+entry.name,"skipping comparison.");
        //Break from chain here
    }).then(() =>{
        return compare("./result/chrome-"+entry.name,"./result/phantom-"+entry.name);
    }).catch((err)=>{
        console.error("Comparison failed");
    }).done();
});

Is there a way to do this?

Thanks for taking the time to read this!

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:8 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
cdhowiecommented, Oct 4, 2016

If I’m understanding this right, you want to write out a specific error message based on the step that failed and then abort the whole process. You can do this by attaching your catch continuations only to the specific promises they belong to, then re-rejecting with the same error, which will cause the outer chain to fall to the end.

Reading the following code, you should clearly be able to see based on the indentation where the catch continuations will apply. Note that the outer chain doesn’t have any catch continuations at all, which is why a rejection in one of the inner chains will fall to the end of the chain.

(I refactored your arrow functions where possible, and wrapped a few calls in Q.try() since I wasn’t sure if those functions returned a promise or a value.)

readdirp({ root: 'data' }).on('data', (entry) => {
    renderer.execute(entry.fullPath, "chrome")
    .then(file =>
        Q.nfcall(fs.writeFile, "./result/chrome-"+entry.name, file)
        .catch(err => {
            console.error("Failed saving file","./result/chrome-"+entry.name,"skipping comparison.");
            // The following line passes the rejection through.  The outer
            // chain of "then"s will by entirely bypassed.
            return Q.reject(err);
        })
    )
    .then(() =>
        Q.try(() => renderer.execute(entry.fullPath,"phantom"))
        .catch(err => {
            console.error("phantom renderer failed", err);
            return Q.reject(err);
        })
    )
    .then(file =>
        Q.nfcall(fs.writeFile, "./result/phantom-"+entry.name, file)
        .catch(err => {
            console.error("Failed saving file","./result/phantom-"+entry.name,"skipping comparison.");
            return Q.reject(err);
        })
    )
    .then(() =>
        Q.try(() => compare("./result/chrome-"+entry.name,"./result/phantom-"+entry.name))
        .catch(err => {
            console.error("Comparison failed");
            return Q.reject(err);
        })
    )
    .done();
});

This annotated version shows how the first error would flow:

    readdirp({ root: 'data' }).on('data', (entry) => {
        renderer.execute(entry.fullPath, "chrome")
        .then(file =>
            Q.nfcall(fs.writeFile, "./result/chrome-"+entry.name, file)
            .catch(err => {
                console.error("Failed saving file","./result/chrome-"+entry.name,"skipping comparison.");
                // The following line passes the rejection through.  The outer
                // chain of "then"s will by entirely bypassed.
/* /-------- */ return Q.reject(err);
/* | */     })
/* | */ )
/* | */ .then(() =>
/* | */     renderer.execute(entry.fullPath,"phantom")
/* | */     .catch(err => {
/* | */         console.error("phantom renderer failed", err);
/* | */         return Q.reject(err);
/* | */     })
/* | */ )
/* | */ .then(file =>
/* | */     Q.nfcall(fs.writeFile, "./result/phantom-"+entry.name, file)
/* | */     .catch(err => {
/* | */         console.error("Failed saving file","./result/phantom-"+entry.name,"skipping comparison.");
/* | */         return Q.reject(err);
/* | */     })
/* | */ )
/* | */ .then(() =>
/* | */     compare("./result/chrome-"+entry.name,"./result/phantom-"+entry.name)
/* | */     .catch(err => {
/* | */         console.error("Comparison failed");
/* | */         return Q.reject(err);
/* | */     })
/* | */ )
/* \> */.done();
    });
0reactions
kriskowalcommented, Feb 27, 2018

Thank you to everyone who helped @pedro93 in this thread.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Break promise chain and call a function based on the step ...
I think in case of rejection in stepOne the second line of code will execute stepTwo but the first will only execute handleErrorOne...
Read more >
How to Break Out of a Promise Chain with JavaScript - YouTube
Ever wonder how to break out of a promise chain with JavaScript? If yes, than you are in the right place. I cover...
Read more >
Breaking and taming the Promise chain in JS
A better way to tame and tidy up your Promise chains, for a cleaner JS code.
Read more >
Promises chaining
In this chapter we cover promise chaining. It looks like this: ... Here the first .then shows 1 and returns new Promise(…) in...
Read more >
Early Returns out of a long promise chain · Issue #581
I think it would be a great feature to have a native break and early return - the existing solutions are exceedingly clunky....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found