成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

對(duì)JavaScript中的異步函數(shù)進(jìn)行異常處理及測(cè)試

bigdevil_s / 3659人閱讀

摘要:總結(jié)最后總結(jié)一下從異步函數(shù)拋出的錯(cuò)誤不會(huì)是普通的異常。異步函數(shù)和異步方法總是返回一個(gè),無(wú)論是已解決還是被拒絕。要攔截異步函數(shù)中的異常,必須使用。

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

本文首發(fā)微信公眾號(hào):jingchengyideng
歡迎關(guān)注,每天都給你推送新鮮的前端技術(shù)文章

可以在 Javascript 的異步函數(shù)中拋出錯(cuò)誤嗎?

這個(gè)話題已被反復(fù)提起過(guò)幾百次,不過(guò)這次讓我們從TDD(Test-Driven Development)的角度來(lái)回答它。

如果你能不在Stackoverflow上搜索就能回答這個(gè)問(wèn)題,會(huì)給我留下深刻的印象。

如果不能的話也可以很酷。 繼續(xù)往下讀,你就能學(xué)到!

你將學(xué)到什么

通過(guò)后面的內(nèi)容你將學(xué)到:

如何從 Javascript 的異步函數(shù)中拋出錯(cuò)誤

如何使用 Jest 測(cè)試來(lái)自異步函數(shù)的異常

要求

要繼續(xù)往下讀你應(yīng)該:

對(duì) Javascript 和 ES6 有基本的了解

安裝 Node.Js 和 Jest

如何從 Javascript 的常規(guī)函數(shù)中拋出錯(cuò)誤

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

拋出錯(cuò)誤是處理未知的最佳方法。

同樣的規(guī)則適用于各種現(xiàn)代語(yǔ)言:Java、Javascript、Python、Ruby。

你可以從函數(shù)中拋出錯(cuò)誤,可以參照以下示例:

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

這是對(duì)它的測(cè)試(使用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 的類中拋出錯(cuò)誤。在 Javascript 中編寫(xiě)類時(shí),我總是在構(gòu)造函數(shù)中輸入意外值。下面是一個(gè)例子:

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

以下是該類的測(cè)試:

"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));
  });
});

測(cè)試確實(shí)通過(guò)了:

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

安排的明明白白!

所以無(wú)論異常是從常規(guī)函數(shù)還是從類構(gòu)造函數(shù)(或從方法)拋出的,一切都會(huì)按照預(yù)期工作。

但是如果我想從異步函數(shù)中拋出錯(cuò)誤怎么辦?

我可以在測(cè)試中使用assert.throws嗎?

各位看官請(qǐng)上眼!

測(cè)試異常

既然都看到這里了,所以你應(yīng)該知道什么是 Javascript 的異步函數(shù),對(duì)嗎?先看一段代碼:

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

假設(shè)你要添加異步方法來(lái)獲取有關(guān)該人的數(shù)據(jù)。這種方法需要一個(gè)網(wǎng)址。如果url不是字符串,就要像上一個(gè)例子中那樣拋出錯(cuò)誤。

先來(lái)修改一下這個(gè)類:

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;

如果我運(yùn)行代碼會(huì)怎么樣?試試吧:

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

結(jié)果是這樣

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.

果然不出所料,異步方法返回了一個(gè)Promise rejection,從嚴(yán)格意義上來(lái)講,并沒(méi)有拋出什么東西。錯(cuò)誤被包含在了Promise rejection中。

換句話說(shuō),我不能使用 assert.throws 來(lái)測(cè)試它。

讓我們通過(guò)測(cè)試來(lái)驗(yàn)證一下:

"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());
  });
});

測(cè)試失敗了!

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.

有沒(méi)有悟出點(diǎn)什么?

看把你能的,來(lái)抓我啊

從嚴(yán)格意義上講異步函數(shù)和異步方法不會(huì)拋出錯(cuò)誤。異步函數(shù)和異步方法總是返回一個(gè)Promise,無(wú)論它已完成還是被拒絕,你必須附上 then() 和 catch(),無(wú)論如何。(或者將方法包裝在try/catch中)。被拒絕的Promise將會(huì)在堆棧中傳播,除非你抓?。╟atch)它。

至于測(cè)試代碼,應(yīng)該這樣寫(xiě):

"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")
    );
  });
});

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

現(xiàn)在測(cè)試通過(guò)了:

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

那代碼該怎么寫(xiě)呢?為了能夠捕獲錯(cuò)誤,你應(yīng)該這樣重構(gòu):

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

現(xiàn)在異常將會(huì)出現(xiàn)在控制臺(tái)中:

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.,有一件重要的事需要注意。

下面的代碼不會(huì)捕獲錯(cuò)誤:

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會(huì)在堆棧中傳播,除非你抓住(catch)它。

要在 try/catch 中正確捕獲錯(cuò)誤,可以像這樣重構(gòu):

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));

這就是它的工作原理。

總結(jié)

最后總結(jié)一下:

從異步函數(shù)拋出的錯(cuò)誤不會(huì)是“普通的異?!?/strong>。

異步函數(shù)和異步方法總是返回一個(gè)Promise,無(wú)論是已解決還是被拒絕。

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

以下是在Jest中測(cè)試異常的規(guī)則:

使用 assert.throws 來(lái)測(cè)試普通函數(shù)和方法中的異常

使用 expect + rejects 來(lái)測(cè)試異步函數(shù)和異步方法中的異常

如果你對(duì)如何使用 Jest 測(cè)試 Koa 2 感興趣,請(qǐng)查看使用Jest和Supertest進(jìn)行測(cè)試的簡(jiǎn)紹這篇文章。

感謝閱讀!

本文首發(fā)微信公眾號(hào):jingchengyideng


歡迎掃描二維碼關(guān)注公眾號(hào),每天都給你推送新鮮的前端技術(shù)文章

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/101412.html

相關(guān)文章

  • 對(duì)JavaScript中的異步函數(shù)進(jìn)行異常處理測(cè)試

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

    paulli3 評(píng)論0 收藏0
  • JavaScript中錯(cuò)誤正確處理方式,你用對(duì)了嗎?

    摘要:?jiǎn)卧獪y(cè)試會(huì)體現(xiàn)出以上錯(cuò)誤處理程序的作用如果出現(xiàn)問(wèn)題,錯(cuò)誤處理程序就會(huì)返回。同時(shí)錯(cuò)誤會(huì)展開(kāi)堆棧,這對(duì)調(diào)試非常有幫助。展開(kāi)堆棧處理異常的一種方式是在調(diào)用堆棧的頂部加入。確保你的錯(cuò)誤處理處在相同域中,這樣會(huì)保留原始消息,堆棧和自定義錯(cuò)誤對(duì)象。 JavaScript的事件驅(qū)動(dòng)范式增添了豐富的語(yǔ)言,也是讓使用JavaScript編程變得更加多樣化。如果將瀏覽器設(shè)想為JavaScript的事件驅(qū)動(dòng)...

    chaos_G 評(píng)論0 收藏0
  • JavaScript 工作原理之四-事件循環(huán)異步編程的出現(xiàn)和 5 種更好的 async/await

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

    maochunguang 評(píng)論0 收藏0
  • 我的 2015 年度小結(jié)(技術(shù)方面)

    摘要:因?yàn)槁酚蓪用媸軜I(yè)務(wù)影響很大,經(jīng)常修改一些功能的行為,所以后來(lái)大部分測(cè)試都是針對(duì)層面的單元測(cè)試。在我了解的過(guò)程中,我發(fā)現(xiàn)中文網(wǎng)絡(luò)上對(duì)的討論非常分散,于是我創(chuàng)建了中文社區(qū),到年末已經(jīng)有個(gè)注冊(cè)用戶和個(gè)帖子了。 https://jysperm.me/2016/02/programming-of-2015/ 從 2014 年末開(kāi)始開(kāi)發(fā)的一個(gè)互聯(lián)網(wǎng)金融項(xiàng)目終于在今年三月份上線了,這是一個(gè) Node...

    宋華 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<