javascript技巧

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript技巧 > JavaScript异常捕获

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

作者:卷帘依旧

为了解决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有什么区别,适用于什么场景

先简单对比一下:

但实际上,这俩并没有优劣之分,但是在某种场景下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. 异常的正确处理方式

异常需要被正确捕获。

小结

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

您可能感兴趣的文章:
阅读全文