瀏覽代碼

Docsify Auto Published

Willin Wang 7 年之前
父節點
當前提交
6c341eba85
共有 3 個文件被更改,包括 163 次插入1 次删除
  1. 1 0
      _sidebar.md
  2. 1 1
      basic/js/tricks.md
  3. 161 0
      basic/js/try-catch.md

+ 1 - 0
_sidebar.md

@@ -25,6 +25,7 @@
     - [Map](basic/js/map.md)
     - [Reduce](basic/js/reduce.md)
     - [正则替换](basic/js/regexp.md)
+    - [异常捕获](basic/js/try-catch.md)
   - Node.js
     - [包管理](basic/node/pkg.md)
     - [Yarn进阶](basic/node/yarn.md)

+ 1 - 1
basic/js/tricks.md

@@ -166,4 +166,4 @@ suite('iterator', function () {
       element.fireEvent('onchange');
     }
   };
-```
+```

+ 161 - 0
basic/js/try-catch.md

@@ -0,0 +1,161 @@
+# 异常捕获
+
+## ES5  中的传统做法
+
+假设代码块执行抛出错误 fail,那么捕获该错误的写法为:
+
+```js
+try {
+  // 代码块执行,并抛出 fail 错误
+  throw new Error('fail');
+} catch (e) {
+  console.log(e);
+}
+```
+
+### 定时器
+
+我们先来针对上面的代码改写一下,加入一个定时器。
+
+```js
+try {
+  setTimeout(()=>{
+    throw new Error('fail');
+    // Uncaught Error: fail
+ 	}, 1000);
+} catch (e) {
+  console.log(e);
+}
+```
+
+像这样,将 try/catch 扔在定时器的外面,是无法捕获到内部的错误的。
+
+正确的做法应该是:
+
+```js
+ setTimeout(()=>{
+  try{
+    throw new Error('fail');
+  } catch (e) {
+    console.log(e);
+  }
+},1000);
+```
+
+### Promise
+
+```js
+function doSomething() {
+  return new Promise((resolve, reject) => {
+    // 同步代码中的 throw 可以被捕捉到
+    throw new Error('fail');
+  });
+}
+
+doSomething()
+  .then((x) => {
+    console.log('success:', x);
+  })
+  .catch((err) => {
+    console.log('fail:', err);
+  });
+```
+
+这样写是没有问题的,错误能够被捕获到。但只要稍微修改一下,可能就出现问题了。比如:
+
+```js
+function doSomething() {
+  return new Promise((resolve, reject) => {
+    // 异步代码中的 throw 不能被 Promise 的 catch 捕捉到
+    setTimeout(() => {
+      throw new Error("fail");
+    }, 1000);
+  });
+}
+
+doSomething()
+  .then((x) => {
+    console.log('success:', x);
+  })
+  .catch((err) => {
+    console.log('fail:', err);
+  });
+```
+
+这里抛出但错误将不能被捕获。所以,在 Promise 中,我们一般通过 reject 来抛出错误。
+
+```js
+function doSomething(x) {
+  return new Promise((resolve, reject) => reject(x));
+}
+
+doSomething('fail').then((x) => {
+  console.log('success:', x);
+}).catch((err) => {
+  console.log('fail:', err);
+});
+// fail: fail
+```
+
+另外,还有一个比较有意思的细节,在 catch 之后继续添加 .then 会被继续执行。
+
+```js
+function doSomething(x) {
+  return new Promise((resolve, reject) => reject(x));
+}
+
+doSomething('fail').then((x) => {
+  console.log('success:', x);
+}).catch((err) => {
+  console.log('fail:', err);
+  // 这里可以写 return 给下面的方法继续执行
+}).then((x) => {
+  console.log('continue:', x);
+});
+// fail: fail
+// continue: undefined
+```
+
+### Async/Await
+
+本质上来讲, Async/Await 是通过 Promise 实现,所以基本跟上面 Promise 所讲的差不多。
+
+可以在 await 方法外嵌套 try/catch,类似这样:
+
+```js
+function doSomething(x) {
+  return new Promise((resolve, reject) => reject(x));
+}
+
+(async () => {
+  try {
+    const result = await doSomething('fail');
+    console.log('success:', result);
+    // return 返回
+  } catch (err) {
+    console.log('fail:', err);
+    // return 返回
+  }
+})();
+// fail: fail
+```
+
+但这里就有一个问题,比如函数需要有返回,那么返回的语句就需要写两次,正常但时候返回结果,错误的时候,返回一个 `throw new Error()` 或者其他的。有一个小的窍门,可以这样写:
+
+```js
+function doSomething(x) {
+  return new Promise((resolve, reject) => reject(x));
+}
+
+(async () => {
+  const result = await doSomething('fail').catch((err) => {
+    console.log('fail:', err);
+    return 0; // 默认值
+  });
+  console.log('success:', result);
+})();
+// fail: fail
+// success: 0
+```
+
+在错误捕获到之后,重新分配一个默认值,让代码继续运行。