问题一

我们先了解一下 try catch 主要捕获的内容的指的是什么?

  • 同步
  • 异步

答案是:try catch 只能捕获同步的错误

// 这种情况setTimeout 为异步程序,捕获不了里面错误的逻辑
try {
  setTimeout(() => {
    throw new Error('e');
  }, 100);
} catch (e) {
  console.log('catch:', e);
}
// 正确的改写为,在异步执行结束后,同步的代码里面进行捕获
setTimeout(() => {
  try {
    throw new Error('e');
  } catch (e) {
     console.log(e);
  }
 }, 100);

问题二

一般JavaScript中会出现的错误类型有哪些,为什么要用到async await

答:

  • 一般情况下会有同步和异步的错误
  • 同步的错误一般的包括js书写错误导致以及程序执行不了的报错
  • 异步的报错主要包括异步程序的执行错误,服务返回的接口调用出现的错误

AsyncIOScheduler 不要退出_默认值

AsyncIOScheduler 不要退出_ecmascript_02

  • 接口调用一般情况下会使用异步的方法比如promiseasync await 针对 XMLHTTPRequest进行封装
  • async await 的出现是为了解决回掉地狱以及多个promise 调用出现的问题

问题三

那我们一般怎么解决异步的报错呢?

方法有很多种

  1. 可以使用try catch
  1. 在异步执行结束后在返回的同步代码中进行捕获
  2. 可以直接将 await 方法添加到 try 当中 进行错误捕获,前提是await中的方法需要有reject 的错误抛出
  1. promise 封装的方法自带有catch 的调用方法可以捕获到报错
  2. 可以使用全局错误捕获拦截
  1. 同步的使用 window.onerror = function(event){},也可以使用dom2级
  2. 异步的使用 window.addEventListener('unhandledrejection', function (event) {})

具体要结合业务场景进行修改

// 中间有报错中断执行走error
try {
  const list = await getList()
  // 有报错执行中断
  const info = await getListByName(list[0]?.name)
} catch (error) {
  console.warn('报错的原因:', error)
}

// 业务判断loading 显示和消失
loading.value = true
let res = await getList().catch(() => (loading.value = false))
if (!res) return

同时有网友提出可以通过插件更便捷的对错误进行捕获

  • 写太多的try catch 影响阅读,可以引入插件进行执行 await-to-js
// await-to-js 插件
/**
 * @param { Promise } promise
 * @param { Object= } errorExt - Additional Information you can pass to the err object
 * @return { Promise }
 */
export function to<T, U = Error>(
  promise: Promise<T>,
  errorExt?: object
): Promise<[U, undefined] | [null, T]> {
  return promise
    .then<[null, T]>((data: T) => [null, data])
    .catch<[U, undefined]>((err: U) => {
      if (errorExt) {
        const parsedError = Object.assign({}, err, errorExt)
        return [parsedError, undefined]
      }

      return [err, undefined]
    })
}

export default to


import to from 'await-to-js'
const [err,res] = to(Promise)
  • 同时也可以在编译的时候,通过 babel 插件在编译的时候针对async await 方法 将内容代码通过try catch 进行包裹 地址
// babel 插件 babel-plugin-await-add-trycatch 
npm install --save-dev babel-plugin-await-add-trycatch
// babel.config.js
module.exports = {
  plugins: [
    [
      require('babel-plugin-await-add-trycatch'),
      {
        exclude: ['build'], // 默认值 ['node_modules']
        include: ['main.js'], // 默认值 []
        customLog: 'My customLog' // 默认值 'Error'
      }
    ]
  ]
};
// 转化前
async function fn() {
  await new Promise((resolve, reject) => reject('报错'));
  await new Promise((resolve) => resolve(1));
  console.log('do something...');
}
fn();
// 转化后
async function fn() {
  try {
    await new Promise((resolve, reject) => reject('报错'));
    await new Promise((resolve) => resolve(1));
    console.log('do something...');
  } catch (e) {
    console.log('\nfilePath: E:\\myapp\\src\\main.js\nfuncName: fn\nError:', e);
  }
}
fn();