我的编程空间,编程开发者的网络收藏夹
学习永远不晚

JavsScript中Promise的错误捕获问题怎么解决

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

JavsScript中Promise的错误捕获问题怎么解决

本篇内容介绍了“JavsScript中Promise的错误捕获问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

我们需要在异步任务中准确的进行错误捕获,以便我们可以知道错误出在什么地方

如果对Promise和trycatch不够理解的话,很多时候会出现Promise中的错误无法被捕获的情况,本文来讨论这些情况

try catch

try catch 只能捕获当前上下文中的错误,也就是只能捕获同步任务的情况,如下场景:

try {    throw "程序执行遇到了一些错误";} catch(e) {    console.log(e)}// 控制台会输出:程序执行遇到了一些错误

这很好,错误被捕获了,我们可以在程序中进程错误的处理;

但是对于异步的任务,trycatch就显得无能为力,不能正确捕获错误:

try {    setTimeout(() => {      throw "程序执行遇到了一些错误"      })} catch(e) {    console.log(e);}// 控制台输出:Uncaught 程序执行遇到了一些错误;

又或者这样:

try {    Promise.reject('程序执行遇到了一些错误');} catch(e) {    console.log(e);}// 控制台输出:Uncaught (in promise) 程序执行遇到了一些错误

上面的代码都无法正常捕获到错误,因为:trycatch永远捕获的是同步的错误

什么是同步的错误?

当在一个事件循环内,同一个任务队列中出现的错误,对于这个任务所在的上下文而言,就是同步错误。

setTimeoutPromise被称为任务源,来自不同的任务源注册的回调函数会被放入不同的任务队列中。

  • setTimeout中的任务会被放入宏任务

  • Promise中的任务会被放入微任务

    • 拓展:setTimeout是宿主浏览器发起的任务,一般会被放入宏任务

    • 而Promise是由JS引擎发起的任务,会被放入微任务

第一次事件循环中,JS引擎会把整个script代码当成一个宏任务执行,执行完成之后,再检测本次循环中是否存在微任务,存在的话就依次从微任务的任务队列中读取执行完所有的微任务,再读取宏任务的任务队列中的任务执行,再执行所有的微任务,如此循环。

JS的执行顺序就是每次事件循环中的宏任务-微任务的不断切换。

再看setTimeout中抛出的错误,这个错误已经不在trycatch所在的事件循环中了,所以这是一个异步错误,无法被trycatch捕获到。

同理,Promise.reject()此处虽然是同步执行的,但是此处reject的内容却在另一个微任务循环中,对于trycatch来讲也不是同步的,所以这两个错误都无法被捕获。

Promise.reject

要理解Promise.reject首先要了解它的返回值,Promise.reject返回的是一个Promise对象,请注意:是Promise对象

Promise对象在任何时候都是一个合法的对象,它不是错误也不是异常,所以在任何实现,直接对Promise.reject或者一个返回Promise对象的调用直接try catch是没有意义的,一个正常的对象永远不可能触发catch捕获。

假设我们由如下代码:

function getData() {    Promise.reject('遇到了一些错误');};function click() {    try {        getData();    } catch(e) {        console.log(e);    }}click(); // 我们模拟业务场景中的click事件// 控制台输出: Uncaught (in promise) 遇到了一些错误

Promise已经通过reject抛出了错误,为什么try catch捕获不到呢?

首先,需要知道,对于一个函数的错误是否可以被捕获到,可以尝试将函数调用的返回值替换到函数调用出,看看是否为一个错误

上面getDate()调用会被替换为undefined

对于一个没有明确return的函数调用,其返回值永远是undefined的,所以代码如下:

function click() {    try {        undefined;    } catch(e) {        console.log(e);    }}

了解js基础的人肯定知道,这不算异常,这个代码会正常执行,不会走到catch中。

可能会有另一种思路,就是将Promise.reject返回出去,那么代码就变成:

function getData() {  return Promise.reject('遇到了一些错误');};function click() {    try {        getData();    } catch(e) {        console.log(e);    }}click();

Promise.reject返回的是一个Promise对象,它是对象,不是错误。所以在try catch中完成getData()调用后这里会出现一个Promise对象,这个对象是一个再正常不过的对象,不会被catch捕获,所以这个try catch依然是无效的。

于是,又出现一种思路:再调用处使用Promise的catch方法进行捕获,于是代码变成:

function getData() {  return Promise.reject('遇到了一些错误');};function click() {    try {        getData().catch(console.log);    } catch(e) {        console.log(e);    }}click();

这是可行的,rejext的错误可以被捕获,但这不是try catch的功劳,而是Promise的内部消化,所以这里的try catch依然没有意义。

解决Promise异常捕获

Promise异常是最常见的异步异常,其内部的错误基本都是被包装成了Promise对象后进行传递,所以解决Promise异步捕获整体思路有两个:

  • 使用Promise的catch方法内部消化;

  • 使用async和await将异步错误转同步错误再由try catch捕获

Promise.catch

对于Promise.reject中抛出的错误,或者Promise构造器中抛出的错误,亦或者then中出现的错误,无论是运行时还是通过throw主动抛出的,原则上都可以被catch捕获。

如下:

function getData() {    Promise.reject('这里发生了错误').catch(console.log);}function click() {    getData();}click();

亦或者在调用处捕获,但这需要被调用的函数能返回Promise对象;

function getData() {    return Promise.reject('程序发生了一些错误');}function click() {    getData().catch(console.log);}click();

上面两个方案都可行,事实上建议在业务逻辑允许的情况下,将Promise都返回出去,以便能向上传递,同时配合**unhandledrejection**进行兜底

async await 异步转同步

使用async和await可以将一个异步函数调用在语义上变成同步执行的效果,这样我们就可以使用try catch去统一处理。

例如:

function getData() {    return Promise.reject('程序发生错误');}async function click() {    try {        await getData();    } catch(e) {        console.log(e);    }}click();

需要注意的是,如果getData方法没有写return, 那么就无法将Promise对象向上传递,那么调用出的await等到的就是一个展开的undefined, 依旧不能进行错误处理。

注意事项

一个函数如果内部处理了Promise异步对象,那么原则上其处理结果应该也是一个Promise对象,对于需要进行错误捕获的场景,Promise对象应该始终通过return向上传递

兜底方案

一般情况下,同步错误如果没有进行捕获,那么这个错误所在的事件循环将终止,所以在开发阶段没有捕获的错误,使用一种方法进行兜底是很有必要的。

对于同步错误,可以定义window.onerror进行兜底处理,或者使用window.addEventListener('error', errHandler)来定义兜底函数。

对于Promise异常,则可以同步使用window.onunhandledrejection或者window.addEventListener('unhandledrejection', errHandler)来定义兜底函数。

我们再讨论then方法中的第二个参数和Promise.catch方法的区别

Promise中的then的第二个参数和catch有什么区别?

  • reject是用来抛出错误的,属于Promise的方法

  • catch是用来处理异常的,属于Promise实例的方法、

  • 区别

    主要区别就是,如果在then的第一个函数中抛出了异常,后面的catch能捕获到,但是then的第二个参数却捕获不到

    then的第二个参数和catch捕获信息的时候会遵循就近原则,如果是promise内部报错,reject抛出错误后,then的第二个参数和catch方法都存在的情况下,只有then的第二个参数能捕获到,如果then的第二个参数不存在,则catch方法会被捕获到。

题: then方法的连续调用,怎么能够知道是第几个then方法报错了呢。

new Promise((resolve,reject) => {    setTimeout(() => {        resolve(1);    }, 1000)}).then(res => {    console.log(res);    return new Promise((resolve,reject) => {        reject('第一个then方法报错了');    })}).then(res => {    console.log(res);    return new Promise((resolve,reject) => {reject('第二个then方法报错了');    })}).catch(err => {    console.log(err);})

“JavsScript中Promise的错误捕获问题怎么解决”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注编程网网站,小编将为大家输出更多高质量的实用文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

JavsScript中Promise的错误捕获问题怎么解决

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

JavsScript中Promise的错误捕获问题怎么解决

本篇内容介绍了“JavsScript中Promise的错误捕获问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!我们需要在异步任务中
2023-07-02

Java中的StackOverflowError错误问题怎么解决

这篇文章主要介绍了Java中的StackOverflowError错误问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Java中的StackOverflowError错误问题怎么解决文章都会有所收获,
2023-07-02

怎么解决php中500错误问题

这篇文章主要为大家展示了“怎么解决php中500错误问题”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“怎么解决php中500错误问题”这篇文章吧。php 500错误的解决办法:1、检查PHP脚本
2023-06-22

java.lang.AssertionError错误问题怎么解决

这篇文章主要介绍了java.lang.AssertionError错误问题怎么解决的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇java.lang.AssertionError错误问题怎么解决文章都会有所收获,
2023-06-30

JavaScript中遇到的错误问题怎么解决

本篇内容介绍了“JavaScript中遇到的错误问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Demo演示每个按钮都会引发一个“
2023-06-02

JavaScript怎么解决ajax中parsererror错误问题

在使用Ajax时,如果遇到`parsererror`错误,这通常意味着服务器返回的数据无法正确解析。下面是一些常见的解决方法:1. 检查服务器返回的数据格式是否正确。通常情况下,服务器返回的数据应该是一个有效的JSON字符串。可以使用`JS
2023-08-09

SpringBoot @NotBlank错误的问题怎么解决

本篇内容主要讲解“SpringBoot @NotBlank错误的问题怎么解决”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“SpringBoot @NotBlank错误的问题怎么解决”吧!Spri
2023-06-20

怎么解决获取VirtualBox COM对象失败错误问题

这篇文章主要介绍“怎么解决获取VirtualBox COM对象失败错误问题”,在日常操作中,相信很多人在怎么解决获取VirtualBox COM对象失败错误问题问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”怎
2023-06-22

怎么解决php redis502错误问题

今天给大家介绍一下怎么解决php redis502错误问题。文章的内容小编觉得不错,现在给大家分享一下,觉得有需要的朋友可以了解一下,希望对大家有所帮助,下面跟着小编的思路一起来阅读吧。php redis502错误的解决办法:1、使用“su
2023-06-29

怎么解决php 535错误问题

今天小编给大家分享一下怎么解决php 535错误问题的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。php 535错误的解决办
2023-06-26

怎么解决php cgi.exe 错误问题

这篇文章主要介绍怎么解决php cgi.exe 错误问题,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!php cgi.exe错误的解决办法:1、执行“c:\php7.1>php-cgi.exe -b 127.0.0.
2023-06-25

Python中ModuleNotFoundError错误的问题解决

本文主要介绍了Python中ModuleNotFoundError错误的问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2023-02-10

怎么解决iis6 php 500错误问题

本篇内容介绍了“怎么解决iis6 php 500错误问题”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!iis6 php 500错误的解决办法
2023-06-21

wordpress标签错误问题怎么解决

本篇内容介绍了“wordpress标签错误问题怎么解决”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!wordp
2023-02-07

怎么解决make hash php错误问题

这篇文章主要介绍了怎么解决make hash php错误问题的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇怎么解决make hash php错误问题文章都会有所收获,下面我们一起来看看吧。make hash p
2023-06-26

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录