Javascript 为什么我不能加入一个承诺。抓住处理者?

Javascript 为什么我不能加入一个承诺。抓住处理者?,javascript,asynchronous,promise,throw,es6-promise,Javascript,Asynchronous,Promise,Throw,Es6 Promise,为什么我不能在catch回调中抛出一个错误,让进程像处理任何其他作用域中的错误一样处理该错误 如果我不执行console.log(err)任何内容都不会打印出来,我也不知道发生了什么。这个过程刚刚结束 例如: function do1() { return new Promise(function(resolve, reject) { throw new Error('do1'); setTimeout(resolve, 1000) }); }

为什么我不能在catch回调中抛出一个
错误
,让进程像处理任何其他作用域中的错误一样处理该错误

如果我不执行
console.log(err)
任何内容都不会打印出来,我也不知道发生了什么。这个过程刚刚结束

例如:

function do1() {
    return new Promise(function(resolve, reject) {
        throw new Error('do1');
        setTimeout(resolve, 1000)
    });
}

function do2() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            reject(new Error('do2'));
        }, 1000)
    });
}

do1().then(do2).catch(function(err) {
    //console.log(err.stack); // This is the only way to see the stack
    throw err; // This does nothing
});

如果回调在主线程中执行,为什么
错误会被黑洞吞没?

这里需要了解的重要事项

  • then
    catch
    函数都返回新的promise对象

  • 无论是抛出还是明确拒绝,都会将当前承诺移动到拒绝状态

  • 由于
    然后
    捕获
    返回新的承诺对象,因此可以将它们链接起来

  • 如果您在承诺处理程序中抛出或拒绝(
    然后
    捕获
    ),它将在链接路径下的下一个拒绝处理程序中处理

  • 正如jfriend00所提到的,
    then
    catch
    处理程序不是同步执行的。当处理程序抛出时,它将立即结束。因此,堆栈将展开,异常将丢失。这就是为什么抛出异常会拒绝当前的承诺


  • 在您的例子中,您通过抛出一个
    错误
    对象来拒绝内部
    do1
    。现在,当前承诺将处于拒绝状态,控制权将被转移到下一个处理程序,在我们的例子中是
    ,然后是

    由于
    then
    处理程序没有拒绝处理程序,因此根本不会执行
    do2
    。您可以使用控制台中的
    console.log
    来确认这一点。由于当前承诺没有拒绝处理程序,因此它也将被拒绝,并带有来自上一个承诺的拒绝值,控制权将被转移到下一个处理程序,即
    catch

    当您执行
    console.log(err.stack)时,
    catch
    是一个拒绝处理程序在它里面,您可以看到错误堆栈跟踪。现在,您正在从中抛出一个
    错误
    对象,因此
    catch
    返回的承诺也将处于拒绝状态

    由于您尚未将任何拒绝处理程序附加到
    捕获
    ,因此无法观察拒绝


    你可以把链条分开,更好地理解这一点,就像这样

    var promise = do1().then(do2);
    
    var promise1 = promise.catch(function (err) {
        console.log("Promise", promise);
        throw err;
    });
    
    promise1.catch(function (err) {
        console.log("Promise1", promise1);
    });
    
    您将获得的输出类似于

    Promise承诺{[Error:do1]}
    承诺1承诺{[Error:do1]}
    
    catch
    处理程序1中,您将得到
    promise
    对象的值作为拒绝


    同样,由
    catch
    处理程序1返回的承诺也被拒绝,其错误与
    promise
    被拒绝的错误相同,我们正在第二个
    catch
    处理程序中观察它。

    此处需要了解的重要事项

  • then
    catch
    函数都返回新的promise对象

  • 无论是抛出还是明确拒绝,都会将当前承诺移动到拒绝状态

  • 由于
    然后
    捕获
    返回新的承诺对象,因此可以将它们链接起来

  • 如果您在承诺处理程序中抛出或拒绝(
    然后
    捕获
    ),它将在链接路径下的下一个拒绝处理程序中处理

  • 正如jfriend00所提到的,
    then
    catch
    处理程序不是同步执行的。当处理程序抛出时,它将立即结束。因此,堆栈将展开,异常将丢失。这就是为什么抛出异常会拒绝当前的承诺


  • 在您的例子中,您通过抛出一个
    错误
    对象来拒绝内部
    do1
    。现在,当前承诺将处于拒绝状态,控制权将被转移到下一个处理程序,在我们的例子中是
    ,然后是

    由于
    then
    处理程序没有拒绝处理程序,因此根本不会执行
    do2
    。您可以使用控制台中的
    console.log
    来确认这一点。由于当前承诺没有拒绝处理程序,因此它也将被拒绝,并带有来自上一个承诺的拒绝值,控制权将被转移到下一个处理程序,即
    catch

    当您执行
    console.log(err.stack)时,
    catch
    是一个拒绝处理程序在它里面,您可以看到错误堆栈跟踪。现在,您正在从中抛出一个
    错误
    对象,因此
    catch
    返回的承诺也将处于拒绝状态

    由于您尚未将任何拒绝处理程序附加到
    捕获
    ,因此无法观察拒绝


    你可以把链条分开,更好地理解这一点,就像这样

    var promise = do1().then(do2);
    
    var promise1 = promise.catch(function (err) {
        console.log("Promise", promise);
        throw err;
    });
    
    promise1.catch(function (err) {
        console.log("Promise1", promise1);
    });
    
    您将获得的输出类似于

    Promise承诺{[Error:do1]}
    承诺1承诺{[Error:do1]}
    
    catch
    处理程序1中,您将得到
    promise
    对象的值作为拒绝

    同样,由
    catch
    处理程序1返回的承诺也被拒绝,其错误与
    promise
    被拒绝的错误相同,我们在第二个
    catch
    处理程序中观察它。

    根据:

    d。如果调用然后抛出异常e,
    A.如果调用了resolvePromise或rejectPromise,请忽略它
    B否则,以e为理由拒绝承诺

    这意味着,若您在
    函数中抛出异常,那个么
    函数将被捕获,您的承诺将被拒绝
    catch
    在这里没有意义,它只是
    的快捷方式。然后(null,function(){})

    我猜你想不经处理地登录
    .catch(function(err) { setTimeout(function() { throw err; }); });
    
    ...
      throw new Error('My error message');
    })
    .catch(function (err) {
      console.error(err.stack);
      process.exit(0);
    });
    
    .catch(function(err) { setTimeout(function() { throw err; }); });
    
    return new Promise((resolve, reject) => {
        reject("err");
    }).catch(err => {
        this.emit("uncaughtException", err);
    
        /* Throw so the promise is still rejected for testing */
        throw err;
    });
    
    function throw_promise_error (error) {
     return new Promise(function (resolve, reject){
      reject(error)
     })
    }
    
    }).then(function (input) {
     if (input === null) {
      let err = {code: 400, reason: 'input provided is null'}
      return throw_promise_error(err)
     } else {
      return noterrorpromise...
     }
    }).then(...).catch(function (error) {
     res.status(error.code).send(error.reason);
    })