国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

對JavaScript中的異步函數進行異常處理及測試

bigdevil_s / 3648人閱讀

摘要:總結最后總結一下從異步函數拋出的錯誤不會是普通的異常。異步函數和異步方法總是返回一個,無論是已解決還是被拒絕。要攔截異步函數中的異常,必須使用。

翻譯:瘋狂的技術宅
原文:https://www.valentinog.com/bl...

本文首發微信公眾號:jingchengyideng
歡迎關注,每天都給你推送新鮮的前端技術文章

可以在 Javascript 的異步函數中拋出錯誤嗎?

這個話題已被反復提起過幾百次,不過這次讓我們從TDD(Test-Driven Development)的角度來回答它。

如果你能不在Stackoverflow上搜索就能回答這個問題,會給我留下深刻的印象。

如果不能的話也可以很酷。 繼續往下讀,你就能學到!

你將學到什么

通過后面的內容你將學到:

如何從 Javascript 的異步函數中拋出錯誤

如何使用 Jest 測試來自異步函數的異常

要求

要繼續往下讀你應該:

對 Javascript 和 ES6 有基本的了解

安裝 Node.Js 和 Jest

如何從 Javascript 的常規函數中拋出錯誤

使用異常而不是返回碼(清潔代碼)

拋出錯誤是處理未知的最佳方法。

同樣的規則適用于各種現代語言:Java、Javascript、Python、Ruby。

你可以從函數中拋出錯誤,可以參照以下示例:

function upperCase(name) {
  if (typeof name !== "string") {
    throw TypeError("name must be a string");
  }
  return name.toUpperCase();
}
module.exports = upperCase;

這是對它的測試(使用Jest):

"use strict";
const assert = require("assert");
const upperCase = require("../function");
describe("upperCase function", () => {
  test("it throws when name is not provided", () => {
    assert.throws(() => upperCase());
  });
  test("it throws when name is not a string", () => {
    assert.throws(() => upperCase(9));
  });
});

也可以從 ES6 的類中拋出錯誤。在 Javascript 中編寫類時,我總是在構造函數中輸入意外值。下面是一個例子:

class Person {
  constructor(name) {
    if (typeof name !== "string") {
      throw TypeError("name must be a string");
    }
    this.name = name;
  }
  // some method here
}
module.exports = Person;

以下是該類的測試:

"use strict";
const assert = require("assert");
const Person = require("../index");
describe("Person class", () => {
  test("it throws when name is not provided", () => {
    assert.throws(() => new Person());
  });
  test("it throws when name is not a string", () => {
    assert.throws(() => new Person(9));
  });
});

測試確實通過了:

PASS  test/index.test.js
 Person class
   ? it throws when name is not provided (1ms)
   ? it throws when name is not a string

安排的明明白白!

所以無論異常是從常規函數還是從類構造函數(或從方法)拋出的,一切都會按照預期工作。

但是如果我想從異步函數中拋出錯誤怎么辦?

我可以在測試中使用assert.throws嗎?

各位看官請上眼!

測試異常

既然都看到這里了,所以你應該知道什么是 Javascript 的異步函數,對嗎?先看一段代碼:

class Person {
  constructor(name) {
    if (typeof name !== "string") {
      throw TypeError("name must be a string");
    }
    this.name = name;
  }
  // some method here
}
module.exports = Person;

假設你要添加異步方法來獲取有關該人的數據。這種方法需要一個網址。如果url不是字符串,就要像上一個例子中那樣拋出錯誤。

先來修改一下這個類:

class Person {
  constructor(name) {
    if (typeof name !== "string") {
      throw TypeError("name must be a string");
    }
    this.name = name;
  }
  async getData(url) {
    if (typeof url !== "string") {
      throw TypeError("url must be a string");
    }
    // const response = await fetch(url)
    // do stuff
  }
}
module.exports = Person;

如果我運行代碼會怎么樣?試試吧:

const Person = require("../index");
const valentinogagliardi = new Person("valentinogagliardi");
valentinogagliardi.getData();

結果是這樣

UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: name must be a string
DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.

果然不出所料,異步方法返回了一個Promise rejection,從嚴格意義上來講,并沒有拋出什么東西。錯誤被包含在了Promise rejection中。

換句話說,我不能使用 assert.throws 來測試它。

讓我們通過測試來驗證一下:

"use strict";
const assert = require("assert");
const Person = require("../index");
describe("Person methods", () => {
  test("it throws when url is not a string", () => {
    const valentinogagliardi = new Person("valentinogagliardi");
    assert.throws(() => valentinogagliardi.getData());
  });
});

測試失敗了!

FAIL  test/index.test.js
  Person methods ? it throws when url is not a string
   assert.throws(function)
   Expected the function to throw an error.
   But it didn"t throw anything.
   Message:
     Missing expected exception.

有沒有悟出點什么?

看把你能的,來抓我啊

從嚴格意義上講異步函數和異步方法不會拋出錯誤。異步函數和異步方法總是返回一個Promise,無論它已完成還是被拒絕,你必須附上 then() 和 catch(),無論如何。(或者將方法包裝在try/catch中)。被拒絕的Promise將會在堆棧中傳播,除非你抓住(catch)它

至于測試代碼,應該這樣寫:

"use strict";
const assert = require("assert");
const Person = require("../index");
describe("Person methods", () => {
  test("it rejects when url is not a string", async () => {
    expect.assertions(1);
    const valentinogagliardi = new Person("valentinogagliardi");
    await expect(valentinogagliardi.getData()).rejects.toEqual(
      TypeError("url must be a string")
    );
  });
});

我們測試的不能是普通的異常,而是帶有TypeError的rejects。

現在測試通過了:

PASS  test/index.test.js
 Person methods
   ? it rejects when url is not a string

那代碼該怎么寫呢?為了能夠捕獲錯誤,你應該這樣重構:

const Person = require("../index");
const valentinogagliardi = new Person("valentinogagliardi");
valentinogagliardi
  .getData()
  .then(res => res)
  .catch(err => console.error(err));

現在異常將會出現在控制臺中:

TypeError: url must be a string
    at Person.getData (/home/valentino/Documenti/articles-and-broadcasts/throw-from-async-functions-2018-04-02/index.js:12:13)
    at Object. (/home/valentino/Documenti/articles-and-broadcasts/throw-from-async-functions-2018-04-02/index.js:22:4)
    // ...

如果你想要更多的try/catch.,有一件重要的事需要注意。

下面的代碼不會捕獲錯誤:

const Person = require("../index");
async function whatever() {
  try {
    const valentinogagliardi = new Person("valentinogagliardi");
    await valentinogagliardi.getData();
    // do stuff with the eventual result and return something
  } catch (error) {
    throw Error(error);
  }
}
whatever();

記住:被拒絕的Promise會在堆棧中傳播,除非你抓住(catch)它。

要在 try/catch 中正確捕獲錯誤,可以像這樣重構:

async function whatever() {
  try {
    const valentinogagliardi = new Person("valentinogagliardi");
    await valentinogagliardi.getData();
    // do stuff with the eventual result and return something
  } catch (error) {
    throw Error(error);
  }
}
whatever().catch(err => console.error(err));

這就是它的工作原理。

總結

最后總結一下:

從異步函數拋出的錯誤不會是“普通的異常”

異步函數和異步方法總是返回一個Promise,無論是已解決還是被拒絕。

要攔截異步函數中的異常,必須使用catch()

以下是在Jest中測試異常的規則:

使用 assert.throws 來測試普通函數和方法中的異常

使用 expect + rejects 來測試異步函數和異步方法中的異常

如果你對如何使用 Jest 測試 Koa 2 感興趣,請查看使用Jest和Supertest進行測試的簡紹這篇文章。

感謝閱讀!

本文首發微信公眾號:jingchengyideng


歡迎掃描二維碼關注公眾號,每天都給你推送新鮮的前端技術文章

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/101412.html

相關文章

  • JavaScript中的異步函數進行異常處理測試

    摘要:總結最后總結一下從異步函數拋出的錯誤不會是普通的異常。異步函數和異步方法總是返回一個,無論是已解決還是被拒絕。要攔截異步函數中的異常,必須使用。 翻譯:瘋狂的技術宅原文:https://www.valentinog.com/bl... 本文首發微信公眾號:jingchengyideng歡迎關注,每天都給你推送新鮮的前端技術文章 可以在 Javascript 的異步函數中拋出錯誤嗎...

    paulli3 評論0 收藏0
  • JavaScript中錯誤正確處理方式,你用了嗎?

    摘要:單元測試會體現出以上錯誤處理程序的作用如果出現問題,錯誤處理程序就會返回。同時錯誤會展開堆棧,這對調試非常有幫助。展開堆棧處理異常的一種方式是在調用堆棧的頂部加入。確保你的錯誤處理處在相同域中,這樣會保留原始消息,堆棧和自定義錯誤對象。 JavaScript的事件驅動范式增添了豐富的語言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設想為JavaScript的事件驅動...

    chaos_G 評論0 收藏0
  • JavaScript 工作原理之四-事件循環異步編程的出現和 5 種更好的 async/await

    摘要:函數會在之后的某個時刻觸發事件定時器。事件循環中的這樣一次遍歷被稱為一個。執行完畢并出棧。當定時器過期,宿主環境會把回調函數添加至事件循環隊列中,然后,在未來的某個取出并執行該事件。 原文請查閱這里,略有改動。 本系列持續更新中,Github 地址請查閱這里。 這是 JavaScript 工作原理的第四章。 現在,我們將會通過回顧單線程環境下編程的弊端及如何克服這些困難以創建令人驚嘆...

    maochunguang 評論0 收藏0
  • 我的 2015 年度小結(技術方面)

    摘要:因為路由層面受業務影響很大,經常修改一些功能的行為,所以后來大部分測試都是針對層面的單元測試。在我了解的過程中,我發現中文網絡上對的討論非常分散,于是我創建了中文社區,到年末已經有個注冊用戶和個帖子了。 https://jysperm.me/2016/02/programming-of-2015/ 從 2014 年末開始開發的一個互聯網金融項目終于在今年三月份上線了,這是一個 Node...

    宋華 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<