Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

    • Ajax
    • Promise
    • Promise 回调
    • async await
    • 跨域
    • try catch
      • 无法捕获
      • Promise 的异常捕获
      • async/await 的异常捕获
    • Generator async await原理
  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

  • 数据结构

  • 算法

  • 手写

  • TypeScript

  • 复盘
  • Async
Mr.w
2020-11-29

try catch

# try/catch

try...catch语句标记要尝试的语句块,并指定一个出现异常时抛出的响应。

看看使用方法:

try {
    throw new Error('The error')
    // .. 下面代码不会执行
    console.log(22)
} catch (err) {
    console.log(err)  // 'The error'
}
1
2
3
4
5
6
7

使用一些不存在的方法,或操作方式错误时,就会进入catch,也是避免某个方法出错,而造成页面奔溃

try {
    JSON(2)
} catch (err) {
    console.log(err)  // JSON is not a functio
}
1
2
3
4
5

# 无法捕获

try {
    setTimeout(() => {
        throw new Error('async error')  // Error
    }, 1000)
} catch(e) {
    console.log(e, 'err')
}
1
2
3
4
5
6
7

这段代码中,setTimeout 的回调函数抛出一个错误,并不会在 catch 中捕获,会导致程序直接报错崩掉。

所以说在 js 中 try/catch 并不是说写上一个就可以高枕无忧了。难道每个函数都要写吗,那什么情况下 try/catch 无法捕获 error 呢?

  • 宏任务的回调函数中的错误无法捕获
// 异步任务
const task = () => {
    setTimeout(() => {
        throw new Error('async error')  // Error
    }, 1000)
}
// 主任务
function main() {
    try {
        task()
    } catch(e) {
        console.log(e, 'err')
    }
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

这种情况下是无法进入 catch 的,这跟浏览器的执行机制有关。 异步任务由 eventloop 加入任务队列,并取出入栈(js 主进程)执行,而当 task 取出执行的时候, main 的栈已经退出了,也就是上下文环境已经改变,所以 main 无法捕获 task 的错误。

  • 微任务(promise)的回调
// 返回一个 promise 对象
const promiseFetch = () => {
    return new Promise((reslove) => {
        reslove();
    })
}
function main() {
    try {
        promiseFetch().then(() => {
            throw new Error('err')  // Error
        })
    } catch(e) {
        console.log(e, 'err');
    }
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

promise 的任务,也就是 then 里面的回调函数,抛出错误同样也无法 catch。 因为微任务队列是在两个 task 之前清空的,所以 then 入栈的时候,main 函数也已经出栈了。

这是事件循环机制的问题,同步任务和异步任务。

# Promise 的异常捕获

function main1() {
  try {
    new Promise(() => {
      throw new Error('promise1 error') // Error
    })
  } catch(e) {
    console.log(e.message);
  }
}

function main2() {
  try {
    Promise.reject('promise2 error')    // Error
  } catch(e) {
    console.log(e.message);
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

以上两个 try catch 都不能捕获到 error,因为 promise 内部的错误不会冒泡出来,而是被 promise 吃掉了,只有通过 promise.catch 才可以捕获,所以用 Promise 一定要写 catch 。

然后我们再来看一下使用 promise.catch 的两段代码:

// reject
new Promise((reslove, reject) => {
    reject()
}).catch((e) => {
    console.log('error')    // error
})

// throw new Error
new Promise((reslove, reject) => {
    throw new Error('error')
}).catch((e) => {
    console.log('error')    // error
})
1
2
3
4
5
6
7
8
9
10
11
12
13

promise 内部的无论是 reject 或者 throw new Error,都可以通过 catch 回调捕获。

这里要跟我们最开始微任务的栗子区分,promise 的微任务指的是 then 的回调,而此处是 Promise 构造函数传入的第一个参数,new Promise 是同步执行的。

那 then 之后的错误如何捕获呢。

Promise.resolve(true).then(() => {
    try {
        throw new Error('then');
    } catch(e) {
        console.log('err')  // err
        return e
    }
}).then(e => {
    console.log(e)  // then
})
1
2
3
4
5
6
7
8
9
10

只能是在回调函数内部 catch 错误,并把错误信息返回,error 会传递到下一个 then 的回调。

# async/await 的异常捕获

首先我们模拟一个请求失败的函数 fetchFailure,fetch 函数通常都是返回一个 promise。

main函数改成 async,catch 去捕获 fetchFailure reject 抛出的错误。能不能获取到呢。

const fetchFailure = () => new Promise((resolve, reject) => {
    setTimeout(() => { // 模拟请求
        reject('fetch failure...')
    })
})
async function main () {
    try {
        const res = await fetchFailure()
        console.log(res, 'res')
    } catch(e) {
        console.log(e, 'e.message')
    }
}
main()
1
2
3
4
5
6
7
8
9
10
11
12
13
14

待定...

JS 异步错误捕获二三事 (opens new window)

跨域
Generator async await原理

← 跨域 Generator async await原理→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式