Javascript 为什么承诺会捕获语法错误?
为什么在出现语法错误时,本机承诺像是一种尝试/捕获 当您需要按顺序执行许多异步操作时,承诺显然在流控制中具有价值。但是,必须为每一个承诺实现自己的错误处理实现,这有时会让它们变得很麻烦 以下面的代码为例:Javascript 为什么承诺会捕获语法错误?,javascript,node.js,promise,Javascript,Node.js,Promise,为什么在出现语法错误时,本机承诺像是一种尝试/捕获 当您需要按顺序执行许多异步操作时,承诺显然在流控制中具有价值。但是,必须为每一个承诺实现自己的错误处理实现,这有时会让它们变得很麻烦 以下面的代码为例: asdf 让一个=新的承诺((决定,拒绝)=>{ asdf }).catch(错误=>{ console.log(错误) console.log(err.stack) })原因是,在处理异步进程时,没有人可以捕捉到错误。 上一个调用堆栈已消失 也就是说: function simulateA
asdf
让一个=新的承诺((决定,拒绝)=>{
asdf
}).catch(错误=>{
console.log(错误)
console.log(err.stack)
})
原因是,在处理异步进程时,没有人可以捕捉到错误。
上一个调用堆栈已消失
也就是说:
function simulateAsyncError () {
try {
setTimeout(function () { throw new Error("Nobody caught me"); }, 1);
console.log("I have set the future error.");
} catch (err) { console.log("I caught it!"); }
}
simulateAsyncError();
// "I have set the future error."
// Uncaught Error: "Nobody caught me"
承诺就是包装它,并处理它。原因是当你处理一个异步进程时,没有人会发现你的错误。 上一个调用堆栈已消失 也就是说:
function simulateAsyncError () {
try {
setTimeout(function () { throw new Error("Nobody caught me"); }, 1);
console.log("I have set the future error.");
} catch (err) { console.log("I caught it!"); }
}
simulateAsyncError();
// "I have set the future error."
// Uncaught Error: "Nobody caught me"
承诺是关于包装和处理的。当代码加载时,Javascript解析器将抛出一个实际的语法错误,并且仍然是一个抛出的异常。基本上,当解析器决定它不能正确解析代码时,在这一点上没有其他的事情可以做。它将放弃并停止解析其余代码 promises将处理运行时错误(发生在代码执行期间,而不是加载/解析期间) 根据规范,
.then()
承诺处理程序是“抛出安全的”,这意味着它们将抛出的异常转换为被拒绝的承诺。之所以这样做,是因为这些处理程序总是异步的,而异步回调中抛出的异常是相当无用的,因为调用代码无法捕获它们,因为调用代码不再在堆栈上,并且只能通过回调通知调用代码。异常最终只会进入一些异步基础设施,在那里没有调用代码可以拦截或处理它们。因此,他们决定将异常转化为拒绝,以便可以使用承诺的所有正常拒绝处理和错误传播
而且,由于调用代码无法捕获异常,如果Promissions没有这样做,那么您必须在几乎每个.then()
处理程序中执行自己的try/catch,以确保捕获到任何错误。因此,它可以节省大量额外的代码,并且可以轻松确保正确捕获所有异步异常,并将错误传播回调用代码
简言之,一旦你习惯了它,它将非常有用,因为一个没有任何地方的异常无论如何都是无用的,我认为设计师做出了一个非常好的选择,决定捕捉异常并使其有用。仅供参考,您仍然可以在
.then()
处理程序中执行自己的try/catch,并根据自己的意愿执行任何操作。加载代码时,Javascript解析器将抛出实际语法错误,并且仍然会引发异常。基本上,当解析器决定它不能正确解析代码时,在这一点上没有其他的事情可以做。它将放弃并停止解析其余代码
promises将处理运行时错误(发生在代码执行期间,而不是加载/解析期间)
根据规范,.then()
承诺处理程序是“抛出安全的”,这意味着它们将抛出的异常转换为被拒绝的承诺。之所以这样做,是因为这些处理程序总是异步的,而异步回调中抛出的异常是相当无用的,因为调用代码无法捕获它们,因为调用代码不再在堆栈上,并且只能通过回调通知调用代码。异常最终只会进入一些异步基础设施,在那里没有调用代码可以拦截或处理它们。因此,他们决定将异常转化为拒绝,以便可以使用承诺的所有正常拒绝处理和错误传播
而且,由于调用代码无法捕获异常,如果Promissions没有这样做,那么您必须在几乎每个.then()
处理程序中执行自己的try/catch,以确保捕获到任何错误。因此,它可以节省大量额外的代码,并且可以轻松确保正确捕获所有异步异常,并将错误传播回调用代码
简言之,一旦你习惯了它,它将非常有用,因为一个没有任何地方的异常无论如何都是无用的,我认为设计师做出了一个非常好的选择,决定捕捉异常并使其有用。仅供参考,您仍然可以在
.then()
处理程序中执行自己的try/catch,并根据需要执行任何操作。承诺不会捕获在解析/编译时发生的典型语法错误。您的示例不是语法错误(解析器不理解您的代码),而是引用错误(解释器/运行时找不到您命名的标识符)
如果文字代码中存在语法错误,则不会捕获到该错误。这就是我们应该期待的:如果它不能解析代码,它就不能知道您已经创建了承诺
let one = new Promise((resolve, reject) => {
foo bar baz
}).catch(err => {
// ignore error
});
请注意,如果在运行时使用eval
生成语法错误(从使用代码的承诺的角度来看),将捕获该错误。区别不在于错误的JavaScript对象类型,而在于编译时错误和运行时错误
let one = new Promise((resolve, reject) => {
eval("foo bar baz");
}).catch(err => {
console.log("Captured error:", err);
})
承诺不会捕获在解析/编译时发生的典型语法错误。您的示例不是语法错误(解析器不理解您的代码),而是引用错误(解释器/运行时找不到您命名的标识符) 如果文字代码中存在语法错误,则不会捕获到该错误。这是我们应该期待的:如果它不能解析代码,它就不能知道这一点
let one = new Promise((resolve, reject) => {
eval("foo bar baz");
}).catch(err => {
console.log("Captured error:", err);
})
Captured error: SyntaxError: Unexpected identifier