当前位置:主页 > 国内 >

鹤岗怯挠电子免费QQ红包群号_关于 promise 吃到错误的理解

关于 promise 吃到错误的理解

下面的内容需要对浏览器原生支持的 promise 的基本用法有了解,如果你还不知道 promise 和 promise 的 catch 方法,你可能需要先在 这里 了解一下。

在 阮一峰大神的 《ECMAScript 6 入门》 关于 Promise 对象那一章在介绍 Promise.prototype.catch() 方法时,里面有一句描述是这样写的 :

跟传统的try/catch代码块不同的是,如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。

一开始我 错误的理解 了这句话的意思,认为是在 promise 内部如果发生错误的话,可以使用 catch 方法来捕获错误,但是如果不使用 catch 方法,它会静悄悄的,不会有报错,就像加了 try-catch 但是在 catch 里面不进行任何处理。

然后我做了一些测试发现和我想的不一样:

首先,试一下在 promise 里面抛出一个异常,看看能不能通过 catch 捕获到

var promise = new Promise(function(resolve, reject) {
    throw new Error("test");   // 这里抛了一个异常
});
promise
    .then(function(value) { console.log(value) })
    .catch((err) => console.log("promise catch err"))

// 控制台输出:
// promise catch err

没什么问题,catch 方法成功捕获到异常了,但是这个异常会不会再被抛到外面去呢?为了以防万一,我们在window 对象上加个 onerror 事件监测一下看看

window.onerror = function () {
    console.log("window err")
} 

var promise = new Promise(function(resolve, reject) {
    throw new Error("test");
});
promise
    .then(function(value) { console.log(value) })
    .catch((err) => console.log("promise catch err"))

// 控制台输出:
// promise catch err

结果还是一样,说明 catch 方法成功捕获到异常而且没有继续往外面抛,这和书里说的一样

那如果去掉 catch 方法呢?我们继续往下看

var promise = new Promise(function(resolve, reject) {
    throw new Error("test");
});
promise.then(function(value) { console.log(value) })    // 这里不捕获异常了

// 控制台输出:
// Uncaught (in promise) Error: test

这里控制台输出了一个报错:Uncaught (in promise) Error: test,咦,如果像书里说的:

跟传统的try/catch代码块不同的是,如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应。

上面说不会有任何反应,那怎么控制台还会报错呢?

我们可以猜测一下,其实这里有点像使用 try-catch 那样捕获了异常然后打印出错误信息后就不再做其他处理一样:

try{
    console.log(x)
}catch(err){
    console.error(err)
}

然后我们加一个 window.onerror 发现,这时 promise 外面添加错误监听事件不会捕获到 promise 对象里面没有进行捕获的错误,像下面这样:

window.onerror = function () {   // 我们添加了 window 的 onerror 处理函数
    console.log("window err")
} 

promise = new Promise(function(resolve, reject) {
    throw new Error("test");
});
promise.then(function(value) { console.log(value) })   

// 控制台输出:
// Uncaught (in promise) Error: test   

可以看到 window 的错误处理事件并没有被触发,所以报错应该是 promise 内部捕获处理的时候直接打印的而没有被抛出,也就验证了我们上面的猜测。

所以到这里,我们可以把书上那句话重新翻译一下得到一条结论

promise 对象里面同步代码抛出的错误在没有通过 promise 的 catch 方法捕获时是会打印报错的(不会阻止 promise 外面代码的执行),但是不会传递到外面触发其他错误监听函数(比如 window.onerror 、try-catch 等)


书上还讲到一个东西也挺奇怪的

window.onerror = function () {
    console.log("window err")
} 

var promise = new Promise(function (resolve, reject) {
    setTimeout(function () { 
        throw new Error("test") 
    }, 0)

    resolve("ok");
});
promise
    .then(function (value) { console.log(value) })
    .catch(() => console.log("promise catch err"))

根据我们上面的理解,你觉得这个控制台会显示什么东西呢?

如果你对答案是 promise catch err,那你就错了,他的结果是:

// 控制台输出:
// ok
// window err
// Uncaught Error: test

这里由于是在 setTimeout 里面抛出错误的,所以报错会在同步代码执行完后的下一轮 “事件循环” 里执行,也就是说当 setTimeout 里面的函数执行后报错时,promise 已经执行完了(所以就算 resolve("ok") 写在 setTimeout 下面也是先输出 ok),所以这个错误是在 Promise 函数体外抛出的,当然也就不会被 promise 的 catch 方法捕获,所以就会传到 window 上被捕获并输出 window err,然后再被浏览器捕获输出Uncaught Error: test,如果在 window onerror 处理程序里面 return true,就不会看到浏览器捕获输出的 Uncaught Error: test 报错。

再看一下 下面的两个例子:

这里是在 promise 里面同步执行了 throw Error 和 resolve 两个操作

window.onerror = function () {
    console.log("window err");
} 

var promise = new Promise(function (resolve, reject) {
    throw new Error("test");
    resolve("ok");
});
promise.then(function (value) { console.log(value) })
    .catch(() => console.log("promise catch err"))

// 控制台输出:
// promise catch err

这里是在 promise 里面用 setTimeout 异步执行了 throw Error 和 resolve 两个操作

window.onerror = function () {
    console.log("window err");
} 

var promise = new Promise(function (resolve, reject) {
    setTimeout(function () {               // 这里包了一个 setTimeout
        throw new Error("test");
        resolve("ok");
    }, 0)
});
promise.then(function (value) { console.log(value) })
    .catch(() => console.log("promise catch err"))

// 控制台输出:
//window err
//Uncaught Error: test

可以看到第二个例子中就算 promise 的状态还是 pedding ,异步操作里面的报错也不会被 promise 的 catch 方法捕获

window. onerror function console. log" window err" var promise new Promise function resolve, reject setTimeout function zhe li bao le yi ge setTimeout throw new Error" test" resolve" ok" , promise. then function value console. log value . catch gt console. log" promise catch err" kong zhi tai shu chu: window err Uncaught Error: test ke yi kan dao di er ge li zi zhong jiu suan promise de zhuang tai hai shi pedding , yi bu cao zuo li mian di bao cuo ye bu hui bei promise de catch fang fa bu huo

所以这里又可以得到一条结论

Promise.prototype.catch() 方法对错误处理和捕获的规则只对 promise 里面的同步执行代码有效,如果此时 promise 里面有异步操作出错的话,是不受 promise 这些规则限制的,而是像正常的报错一样处理。

总结:

  1. promise 对象里面同步代码抛出的错误在没有通过 promise 的 catch 方法捕获时是会打印报错的(不会阻止 promise 外面代码的执行),但是不会传递到外面触发其他错误监听函数(比如 window.onerror 、try-catch 等)
  2. Promise.prototype.catch() 方法对错误处理和捕获的规则只对 promise 里面的同步执行代码有效,如果此时 promise 里面有异步操作出错的话,是不受 promise 这些规则限制的,而是像正常的报错一样处理。
  3. 其实上面两条规则可以看出 promise 对错误的处理应该是在内部使用了像 try-catch 的方式处理了错误,所以异步的它是处理不了的。就行下面这样一样,try-catch 并不会捕获到错误,错误会被 window.onerror 捕获
window.onerror = function () {
    console.log("window err");
    return true
} 

try{
    setTimeout(function () { 
        console.log(x)    // 这里 x 未定义
    }, 10)
}catch(err){
    console.log("try err")
}

// 控制台输出:
//window err

最后,可能还会有一些理解上的错误,希望大家多多指正。

当前文章:http://www.mywifiid.com/463imta47/18040-1101650-47324.html

发布时间:05:32:33

2018香港历史开奖记录??金彩网现扬开码84384??本港台现场报码1香港现场开奖1即??www.666804.com??www.205222.com??本港台高手论坛??免费心水论坛??博彩论坛www.993927.com??333046.com??大赢家心水论坛一集结??

相关新闻

最后更新

热门新闻