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

資訊專欄INFORMATION COLUMN

ES6 系列之我們來聊聊 Async

Songlcy / 3375人閱讀

摘要:標(biāo)準(zhǔn)引入了函數(shù),使得異步操作變得更加方便。在異步處理上,函數(shù)就是函數(shù)的語法糖。在實(shí)際項(xiàng)目中,錯(cuò)誤處理邏輯可能會(huì)很復(fù)雜,這會(huì)導(dǎo)致冗余的代碼。的出現(xiàn)使得就可以捕獲同步和異步的錯(cuò)誤。如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤剑?qǐng)務(wù)必給予指正,十分感謝。

async

ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù),使得異步操作變得更加方便。

在異步處理上,async 函數(shù)就是 Generator 函數(shù)的語法糖。

舉個(gè)例子:

// 使用 generator
var fetch = require("node-fetch");
var co = require("co");

function* gen() {
    var r1 = yield fetch("https://api.github.com/users/github");
    var json1 = yield r1.json();
    console.log(json1.bio);
}

co(gen);

當(dāng)你使用 async 時(shí):

// 使用 async
var fetch = require("node-fetch");

var fetchData = async function () {
    var r1 = await fetch("https://api.github.com/users/github");
    var json1 = await r1.json();
    console.log(json1.bio);
};

fetchData();

其實(shí) async 函數(shù)的實(shí)現(xiàn)原理,就是將 Generator 函數(shù)和自動(dòng)執(zhí)行器,包裝在一個(gè)函數(shù)里。

async function fn(args) {
  // ...
}

// 等同于

function fn(args) {
  return spawn(function* () {
    // ...
  });
}

spawn 函數(shù)指的是自動(dòng)執(zhí)行器,就比如說 co。

再加上 async 函數(shù)返回一個(gè) Promise 對(duì)象,你也可以理解為 async 函數(shù)是基于 Promise 和 Generator 的一層封裝。

async 與 Promise

嚴(yán)謹(jǐn)?shù)恼f,async 是一種語法,Promise 是一個(gè)內(nèi)置對(duì)象,兩者并不具備可比性,更何況 async 函數(shù)也返回一個(gè) Promise 對(duì)象……

這里主要是展示一些場景,使用 async 會(huì)比使用 Promise 更優(yōu)雅的處理異步流程。

1. 代碼更加簡潔
/**
 * 示例一
 */
function fetch() {
  return (
    fetchData()
    .then(() => {
      return "done"
    });
  )
}

async function fetch() {
  await fetchData()
  return "done"
};
/**
 * 示例二
 */
function fetch() {
  return fetchData()
  .then(data => {
    if (data.moreData) {
        return fetchAnotherData(data)
        .then(moreData => {
          return moreData
        })
    } else {
      return data
    }
  });
}

async function fetch() {
  const data = await fetchData()
  if (data.moreData) {
    const moreData = await fetchAnotherData(data);
    return moreData
  } else {
    return data
  }
};
/**
 * 示例三
 */
function fetch() {
  return (
    fetchData()
    .then(value1 => {
      return fetchMoreData(value1)
    })
    .then(value2 => {
      return fetchMoreData2(value2)
    })
  )
}

async function fetch() {
  const value1 = await fetchData()
  const value2 = await fetchMoreData(value1)
  return fetchMoreData2(value2)
};
2. 錯(cuò)誤處理
function fetch() {
  try {
    fetchData()
      .then(result => {
        const data = JSON.parse(result)
      })
      .catch((err) => {
        console.log(err)
      })
  } catch (err) {
    console.log(err)
  }
}

在這段代碼中,try/catch 能捕獲 fetchData() 中的一些 Promise 構(gòu)造錯(cuò)誤,但是不能捕獲 JSON.parse 拋出的異常,如果要處理 JSON.parse 拋出的異常,需要添加 catch 函數(shù)重復(fù)一遍異常處理的邏輯。

在實(shí)際項(xiàng)目中,錯(cuò)誤處理邏輯可能會(huì)很復(fù)雜,這會(huì)導(dǎo)致冗余的代碼。

async function fetch() {
  try {
    const data = JSON.parse(await fetchData())
  } catch (err) {
    console.log(err)
  }
};

async/await 的出現(xiàn)使得 try/catch 就可以捕獲同步和異步的錯(cuò)誤。

3. 調(diào)試
const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, 1))
const fetchMoreData = (value) => new Promise((resolve) => setTimeout(resolve, 1000, value + 1))
const fetchMoreData2 = (value) => new Promise((resolve) => setTimeout(resolve, 1000, value + 2))

function fetch() {
  return (
    fetchData()
    .then((value1) => {
      console.log(value1)
      return fetchMoreData(value1)
    })
    .then(value2 => {
      return fetchMoreData2(value2)
    })
  )
}

const res = fetch();
console.log(res);

因?yàn)?then 中的代碼是異步執(zhí)行,所以當(dāng)你打斷點(diǎn)的時(shí)候,代碼不會(huì)順序執(zhí)行,尤其當(dāng)你使用 step over 的時(shí)候,then 函數(shù)會(huì)直接進(jìn)入下一個(gè) then 函數(shù)。

const fetchData = () => new Promise((resolve) => setTimeout(resolve, 1000, 1))
const fetchMoreData = () => new Promise((resolve) => setTimeout(resolve, 1000, 2))
const fetchMoreData2 = () => new Promise((resolve) => setTimeout(resolve, 1000, 3))

async function fetch() {
  const value1 = await fetchData()
  const value2 = await fetchMoreData(value1)
  return fetchMoreData2(value2)
};

const res = fetch();
console.log(res);

而使用 async 的時(shí)候,則可以像調(diào)試同步代碼一樣調(diào)試。

async 地獄

async 地獄主要是指開發(fā)者貪圖語法上的簡潔而讓原本可以并行執(zhí)行的內(nèi)容變成了順序執(zhí)行,從而影響了性能,但用地獄形容有點(diǎn)夸張了點(diǎn)……

例子一

舉個(gè)例子:

(async () => {
  const getList = await getList();
  const getAnotherList = await getAnotherList();
})();

getList() 和 getAnotherList() 其實(shí)并沒有依賴關(guān)系,但是現(xiàn)在的這種寫法,雖然簡潔,卻導(dǎo)致了 getAnotherList() 只能在 getList() 返回后才會(huì)執(zhí)行,從而導(dǎo)致了多一倍的請(qǐng)求時(shí)間。

為了解決這個(gè)問題,我們可以改成這樣:

(async () => {
  const listPromise = getList();
  const anotherListPromise = getAnotherList();
  await listPromise;
  await anotherListPromise;
})();

也可以使用 Promise.all():

(async () => {
  Promise.all([getList(), getAnotherList()]).then(...);
})();
例子二

當(dāng)然上面這個(gè)例子比較簡單,我們?cè)賮頂U(kuò)充一下:

(async () => {
  const listPromise = await getList();
  const anotherListPromise = await getAnotherList();

  // do something

  await submit(listData);
  await submit(anotherListData);

})();

因?yàn)?await 的特性,整個(gè)例子有明顯的先后順序,然而 getList() 和 getAnotherList() 其實(shí)并無依賴,submit(listData) 和 submit(anotherListData) 也沒有依賴關(guān)系,那么對(duì)于這種例子,我們?cè)撛趺锤膶懩兀?/p>

基本分為三個(gè)步驟:

1. 找出依賴關(guān)系

在這里,submit(listData) 需要在 getList() 之后,submit(anotherListData) 需要在 anotherListPromise() 之后。

2. 將互相依賴的語句包裹在 async 函數(shù)中

async function handleList() {
  const listPromise = await getList();
  // ...
  await submit(listData);
}

async function handleAnotherList() {
  const anotherListPromise = await getAnotherList()
  // ...
  await submit(anotherListData)
}

3.并發(fā)執(zhí)行 async 函數(shù)

async function handleList() {
  const listPromise = await getList();
  // ...
  await submit(listData);
}

async function handleAnotherList() {
  const anotherListPromise = await getAnotherList()
  // ...
  await submit(anotherListData)
}

// 方法一
(async () => {
  const handleListPromise = handleList()
  const handleAnotherListPromise = handleAnotherList()
  await handleListPromise
  await handleAnotherListPromise
})()

// 方法二
(async () => {
  Promise.all([handleList(), handleAnotherList()]).then()
})()
繼發(fā)與并發(fā)

問題:給定一個(gè) URL 數(shù)組,如何實(shí)現(xiàn)接口的繼發(fā)和并發(fā)?

async 繼發(fā)實(shí)現(xiàn):

// 繼發(fā)一
async function loadData() {
  var res1 = await fetch(url1);
  var res2 = await fetch(url2);
  var res3 = await fetch(url3);
  return "whew all done";
}
// 繼發(fā)二
async function loadData(urls) {
  for (const url of urls) {
    const response = await fetch(url);
    console.log(await response.text());
  }
}

async 并發(fā)實(shí)現(xiàn):

// 并發(fā)一
async function loadData() {
  var res = await Promise.all([fetch(url1), fetch(url2), fetch(url3)]);
  return "whew all done";
}
// 并發(fā)二
async function loadData(urls) {
  // 并發(fā)讀取 url
  const textPromises = urls.map(async url => {
    const response = await fetch(url);
    return response.text();
  });

  // 按次序輸出
  for (const textPromise of textPromises) {
    console.log(await textPromise);
  }
}
async 錯(cuò)誤捕獲

盡管我們可以使用 try catch 捕獲錯(cuò)誤,但是當(dāng)我們需要捕獲多個(gè)錯(cuò)誤并做不同的處理時(shí),很快 try catch 就會(huì)導(dǎo)致代碼雜亂,就比如:

async function asyncTask(cb) {
    try {
       const user = await UserModel.findById(1);
       if(!user) return cb("No user found");
    } catch(e) {
        return cb("Unexpected error occurred");
    }

    try {
       const savedTask = await TaskModel({userId: user.id, name: "Demo Task"});
    } catch(e) {
        return cb("Error occurred while saving task");
    }

    if(user.notificationsEnabled) {
        try {
            await NotificationService.sendNotification(user.id, "Task Created");
        } catch(e) {
            return cb("Error while sending notification");
        }
    }

    if(savedTask.assignedUser.id !== user.id) {
        try {
            await NotificationService.sendNotification(savedTask.assignedUser.id, "Task was created for you");
        } catch(e) {
            return cb("Error while sending notification");
        }
    }

    cb(null, savedTask);
}

為了簡化這種錯(cuò)誤的捕獲,我們可以給 await 后的 promise 對(duì)象添加 catch 函數(shù),為此我們需要寫一個(gè) helper:

// to.js
export default function to(promise) {
   return promise.then(data => {
      return [null, data];
   })
   .catch(err => [err]);
}

整個(gè)錯(cuò)誤捕獲的代碼可以簡化為:

import to from "./to.js";

async function asyncTask() {
     let err, user, savedTask;

     [err, user] = await to(UserModel.findById(1));
     if(!user) throw new CustomerError("No user found");

     [err, savedTask] = await to(TaskModel({userId: user.id, name: "Demo Task"}));
     if(err) throw new CustomError("Error occurred while saving task");

    if(user.notificationsEnabled) {
       const [err] = await to(NotificationService.sendNotification(user.id, "Task Created"));
       if (err) console.error("Just log the error and continue flow");
    }
}
async 的一些討論 async 會(huì)取代 Generator 嗎?

Generator 本來是用作生成器,使用 Generator 處理異步請(qǐng)求只是一個(gè)比較 hack 的用法,在異步方面,async 可以取代 Generator,但是 async 和 Generator 兩個(gè)語法本身是用來解決不同的問題的。

async 會(huì)取代 Promise 嗎?

async 函數(shù)返回一個(gè) Promise 對(duì)象

面對(duì)復(fù)雜的異步流程,Promise 提供的 all 和 race 會(huì)更加好用

Promise 本身是一個(gè)對(duì)象,所以可以在代碼中任意傳遞

async 的支持率還很低,即使有 Babel,編譯后也要增加 1000 行左右。

參考

(譯) 6 個(gè) Async/Await 優(yōu)于 Promise 的方面

(譯) 如何逃離 async/await 地獄

精讀《async/await 是把雙刃劍》

ECMAScript 6 入門

How to write async await without try-catch blocks in Javascript

ES6 系列

ES6 系列目錄地址:https://github.com/mqyqingfeng/Blog

ES6 系列預(yù)計(jì)寫二十篇左右,旨在加深 ES6 部分知識(shí)點(diǎn)的理解,重點(diǎn)講解塊級(jí)作用域、標(biāo)簽?zāi)0?、箭頭函數(shù)、Symbol、Set、Map 以及 Promise 的模擬實(shí)現(xiàn)、模塊加載方案、異步處理等內(nèi)容。

如果有錯(cuò)誤或者不嚴(yán)謹(jǐn)?shù)牡胤?,?qǐng)務(wù)必給予指正,十分感謝。如果喜歡或者有所啟發(fā),歡迎 star,對(duì)作者也是一種鼓勵(lì)。

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/98642.html

相關(guān)文章

  • ES6 完全使用手冊(cè)

    摘要:前言這里的泛指之后的新語法這里的完全是指本文會(huì)不斷更新這里的使用是指本文會(huì)展示很多的使用場景這里的手冊(cè)是指你可以參照本文將項(xiàng)目更多的重構(gòu)為語法此外還要注意這里不一定就是正式進(jìn)入規(guī)范的語法。 前言 這里的 ES6 泛指 ES5 之后的新語法 這里的 完全 是指本文會(huì)不斷更新 這里的 使用 是指本文會(huì)展示很多 ES6 的使用場景 這里的 手冊(cè) 是指你可以參照本文將項(xiàng)目更多的重構(gòu)為 ES6...

    kgbook 評(píng)論0 收藏0
  • 前端進(jìn)階資源整理

    摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開發(fā)中所謂狀態(tài)淺析從時(shí)間旅行的烏托邦,看狀態(tài)管理的設(shè)計(jì)誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時(shí)間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個(gè)故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...

    BlackMass 評(píng)論0 收藏0
  • javascript異步與promise

    摘要:到這里,我已經(jīng)發(fā)出了一個(gè)請(qǐng)求買漢堡,啟動(dòng)了一次交易。但是做漢堡需要時(shí)間,我不能馬上得到這個(gè)漢堡,收銀員給我一個(gè)收據(jù)來代替漢堡。到這里,收據(jù)就是一個(gè)承諾保證我最后能得到漢堡。 同期異步系列文章推薦談一談javascript異步j(luò)avascript異步中的回調(diào)javascript異步之Promise.all()、Promise.race()、Promise.finally()javascr...

    rollback 評(píng)論0 收藏0
  • ES6 系列我們聊聊裝飾器

    摘要:第二部分源碼解析接下是應(yīng)用多個(gè)第二部分對(duì)于一個(gè)方法應(yīng)用了多個(gè),比如會(huì)編譯為在第二部分的源碼中,執(zhí)行了和操作,由此我們也可以發(fā)現(xiàn),如果同一個(gè)方法有多個(gè)裝飾器,會(huì)由內(nèi)向外執(zhí)行。有了裝飾器,就可以改寫上面的代碼。 Decorator 裝飾器主要用于: 裝飾類 裝飾方法或?qū)傩? 裝飾類 @annotation class MyClass { } function annotation(ta...

    eternalshallow 評(píng)論0 收藏0
  • ES6 系列我們聊聊 Promise

    前言 Promise 的基本使用可以看阮一峰老師的 《ECMAScript 6 入門》。 我們來聊點(diǎn)其他的。 回調(diào) 說起 Promise,我們一般都會(huì)從回調(diào)或者回調(diào)地獄說起,那么使用回調(diào)到底會(huì)導(dǎo)致哪些不好的地方呢? 1. 回調(diào)嵌套 使用回調(diào),我們很有可能會(huì)將業(yè)務(wù)代碼寫成如下這種形式: doA( function(){ doB(); doC( function(){ ...

    MycLambert 評(píng)論0 收藏0

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

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<