关于JavaScript异常捕获的几点建议

 更新时间:2026年06月10日 09:31:02   作者:卷帘依旧  
为了解决JavaScript回调地狱的问题,ES6+引入了Promise,通过将返回值代理到Promise中,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

为了解决JavaScript回调地狱的问题,ES6+引入了Promise,通过将返回值代理到Promise中,并结合pending, rejected, fulfilled三种状态的转化返回Promise,将异步的返回值存储在未来某一时刻可以用到的promise中,方便解析。

Promise通过then()链的方式调用,发生错误时通过rejected promise传递错误,可以像try...catch一样捕获和处理异常,但是使用不当可能导致意料之外的行为,本文列举了一些常见的使用错误,在使用中应当注意。

1.then链式调用异步,捕获不到异常

👉🏻现象:在.then()链中调用异步函数,某些调用方式不同会导致捕获不到异步抛出的异常

异步函数异常捕获demo-sandbox

const before = () => {
    const p = new Promise((resolve, reject) => {
        // resolve('before')
        console.log('ok');
        reject(new Error('error!!!'));
    });
    return p;
};
const handleClick = () => {
    const p = new Promise((resolve, reject) => {
        resolve(true);
    });
    p
        // ❌ catch不到
        .then(() => {
            before(); 
        })
        // .then(before)
        // .then(async () => {
        //   await before();
        // })
        .then(() => {
            console.log('then');
        })
        .catch(e => {
            console.error(e);
        });
};

💡原因

缺少return语句:before()没有return,返回undefined,无错误抛出,后续的then链会继续执行,但是因为错误没有被捕获/正确处理,会导致页面或应用程序崩溃。

❓疑惑

rejected promise不就是异常吗,那为什么没有触发呢?

⭐️ The return is implicit under some circumstances

实际上rejected promise并不是异常,如果不被return出去,就不会触发error机制(类似的,如果创建一个新的错误对象,但是没有throw,那么同样也不会触发异常)

实际上,rejected promise并不是异常,如果没有return出去,那么就不会触发error

2. try...catch无法捕获异步函数中通过return返回的rejected error.

👉🏻需要使用await接收异步函数的返回,再将结果return出去

const a = async () => {
    return new Promise((resolve, reject) => {
        reject('error')
    })
};
const b = async () => {
    try {
        // ❌捕获不到
        // return a();
        const res = await a();
        return res;
    }
    catch (e) {
        console.log('catch exception!!!')
    }
}
b();

3. 在Promise的构造函数中使用async会导致异常捕获不到

let p = new Promise(resolve => {
  ""(); // TypeError
  resolve();
});
(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Catches it.
let p = new Promise(async resolve => {
  ""(); // TypeError
  resolve();
});
(async () => {
  await p;
})().catch(e => console.log("Caught: " + e)); // Doesn't catch it!

💡第一段代码能够捕获到异常,因为异常由Promise的构造函数直接reject出去;第二段代码不能,因为async关键字会隐式生成一个新的promise,由async函数自身处理。

4.JavaScript Reject V.S. Throw

都是用于抛出异常,reject和throw有什么区别,适用于什么场景

先简单对比一下:

  • 都可用于触发错误机制
  • reject是promise的一部分,结合promise使用;throw不受限制
  • throw之后的语句都不会执行了,reject之后的语句会正常执行,但如果reject前边有return,那么其后的语句同样也不会继续执行

但实际上,这俩并没有优劣之分,但是在某种场景下throw是无效的。在promise的回调中throw可以正常使用,一旦出现异步,throw就无效了。

比如:

new Promise(function() {
  setTimeout(function() {
    throw 'or nah';
    // return Promise.reject('or nah'); also won't work
  }, 1000);
}).catch(function(e) {
  console.log(e); // doesn't happen
});

正确捕获的方式:

new Promise((resolve, reject) => {
  setTimeout(function() {
    reject('or nah');
  }, 1000);
}).catch(function(e) {
  console.log(e); // works
});

5. 异常的正确处理方式

异常需要被正确捕获。

  • 嵌套的try...catch

    如果代码中有嵌套的try...catch,那么异常会被内部的catch捕获:内层异常被处理,那么外层就捕获不到了;内层直接throw,那么内层try...catch无意义

  • .then链的异常捕获,需要保证异常在UI层被捕获。

    不要过早的吞掉异常,需要保证catch在最终调用处调用,避免异常暴露导致程序或页面崩溃。

小结

  • rejected promise和throw都可用于触发异常,没有优劣之分;
  • promise回调中存在异步,那么rejected promise必要要return出去才可被后续处理,否则返回undefined,即使存在异常也不会被处理,会导致页面或应用程序崩溃;
  • promise回调中的异步函数,执行结果需要被return出去异常才会被捕获:要么直接作为回调参数,要么使用async...await执行,要么使用return
  • 捕获promise回调中异步函数的异常,throw是无效的,创建一个新的rejected promise也是无效的,需要使用当前promise的rejecte函数
  • 在promise的构造函数中使用async关键字会导致异常捕获不到,因为async关键字会隐式生成一个新的promise,由async函数自身处理

到此这篇关于关于JavaScript异常捕获的几点建议的文章就介绍到这了,更多相关JavaScript异常捕获内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 小程序获取当前位置加搜索附近热门小区及商区的方法

    小程序获取当前位置加搜索附近热门小区及商区的方法

    这篇文章主要介绍了小程序获取当前位置加搜索附近热门小区及商区的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • 基于javascript的异步编程实例详解

    基于javascript的异步编程实例详解

    这篇文章主要介绍了基于javascript的异步编程,结合实例形式分析了javascript异步编程的原理、实现技巧与相关注意事项,需要的朋友可以参考下
    2017-04-04
  • JavaScript判断变量是否为数组的方法(Array)

    JavaScript判断变量是否为数组的方法(Array)

    这篇文章主要介绍了JavaScript判断变量是否为数组的方法(Array),涉及到javascript 数组 变量相关知识,感兴趣的朋友一起学习吧
    2016-02-02
  • CSS常用网站布局实例

    CSS常用网站布局实例

    PS:这里列出的是常用的例子,而非研究之用,对一每个盒子,都没有设置margin,padding,boeder等属性!
    2008-04-04
  • 小程序开发中如何使用async-await并封装公共异步请求的方法

    小程序开发中如何使用async-await并封装公共异步请求的方法

    在平常的项目开发中肯定会遇到同步异步执行的问题,这篇文章主要介绍了小程序开发中如何使用async-await并封装公共异步请求的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-01-01
  • 自己做的模拟模态对话框实现代码

    自己做的模拟模态对话框实现代码

    最近做完一个项目,发现浏览器兼容问题,模态对话框只有IE支持,但是IE9又不能支持带框架的对话框,那个对话框的大小打死都设置不了,在网上查说因为好多功能被IE9屏蔽了,于是自己做了一个模拟对话框的东西
    2012-05-05
  • 深度解析JavaScript对象继承

    深度解析JavaScript对象继承

    JavaScript中的对象继承是构建灵活、可维护代码的关键部分,本文主要介绍了深度解析JavaScript对象继承,包括原型链继承、构造函数继承、组合继承等,感兴趣的可以了解一下
    2024-01-01
  • 移动前端图片压缩上传的实例

    移动前端图片压缩上传的实例

    下面小编就为大家分享一篇移动前端图片压缩上传的实例。具有很好的参考价值,希望对大家有所帮助。一起小编过来看看吧
    2017-12-12
  • 前端兼容性问题全面解决方案示例代码

    前端兼容性问题全面解决方案示例代码

    市场上浏览器种类很多,不同浏览器的内核也不尽相同,所以各个浏览器对网页的解析存在一定的差异,这篇文章主要介绍了前端兼容性问题全面解决方案的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下
    2025-09-09
  • javascript稀疏数组(sparse array)和密集数组用法分析

    javascript稀疏数组(sparse array)和密集数组用法分析

    这篇文章主要介绍了javascript稀疏数组(sparse array)和密集数组用法,分析javascript稀疏数组和密集数组的功能、定义与使用方法,需要的朋友可以参考下
    2016-12-12

最新评论