Promise.prototype.uncaught

  1. It depends on whether you want to handle uncaught situation in a middle state or in the end? If in the middle, a prototype method is proper, while a global method is proper in the end.

  2. Take node implementation as an example, unhandledRejection will also be fired in two situations:

    process.on('unhandledRejection', () => console.log('unhandled'));
    
  • Use Promise.reject directly:

    Promise.reject(1); // fired
    new Promise((ignore, reject) => reject(1)); // fired
    
  • Two embedded async / await function:

    (async () => { await Promise.reject(1); })(); // fired
    (async () => { await (() => Promise.reject(1))(); })(); // fired
    

    For these two examples, we should also trigger 'uncaught' because developers do exactly not catch such exceptions.

  1. My assume is like the following snippet:

    Promise.reject(1).uncaught(() => { throw new Error('1 has been uncught'); }); // throw uncaught
    Promise.reject(1).catch(result => result > 1 ? Promise.reject(1) : true)
        .uncaught(() => { throw new Error('1 has been uncught'); }); // throw uncaught
    
    
    Promise.reject(1).catch(result => result > 1 ? Promise.reject(1) : true)
        .then(console.log) // => true (the reuslt has been caught)
        .uncaught(() => { throw new Error('1 has been uncught'); }); // won't throw uncaught
    

    In such a handler, the whole Promise chain should act depend on what it returns:

    Promise.reject(1).uncaught(() => Promise.resolve(2)).then(console.log); // => 2
    Promise.reject(2).uncaught(() => Promise.reject(2)).then(ignore, console.log); // => 2
    

    If you want a default handler does not change the state of a Promise, we can define another two methods like Promise.prototype.onFail or Promise.prototype.onSuccess to support for default successful or failed handling:

    Promise.reject(1).onFail(console.log); // => 1
    Promise.reject(2).then(ignore, () => Promise.resolve(1)).onSuccess(console.log); // => 2