摘要:總結(jié)這篇文章簡(jiǎn)單的介紹了一些常用的異步編程的方法,如果有錯(cuò)誤或不嚴(yán)謹(jǐn)?shù)牡胤剑瑲g迎批評(píng)指正,如果喜歡,歡迎點(diǎn)贊收藏。
大家都知道js的執(zhí)行環(huán)境是單線程的,如果沒有異步編程,那么js的執(zhí)行效率會(huì)非常低下,導(dǎo)致程序十分卡頓,一提到異步編程大家首先的想到的一定是回調(diào)函數(shù),這也是最常用的異步編程的形式,但其實(shí)常用的還有Promise和Async函數(shù),接下來就讓我們一起學(xué)習(xí)這幾種常用的異步編程方法。
回調(diào)函數(shù)回調(diào)函數(shù)就是把任務(wù)的第二段多帶帶寫在一個(gè)函數(shù)里面,等到重新執(zhí)行這個(gè)任務(wù)的時(shí)候,就直接調(diào)用這個(gè)函數(shù),來看一個(gè)簡(jiǎn)單的例子:
function print(name, callback) { setTimeout(() => { console.log(name) if (callback) { callback() } }, 1000) } print("a", function () { print("b") })
上面這個(gè)例子中將print("b")放在print("a")的回調(diào)函數(shù)中,這樣就能按順序依次打印a、b,但是回調(diào)函數(shù)有一個(gè)很明顯的問題,就是當(dāng)回調(diào)函數(shù)嵌套過深時(shí),會(huì)導(dǎo)致代碼混亂,不夠清晰,這就是人們常說的對(duì)調(diào)地獄,來看下面這個(gè)例子:
function print(name, callback) { setTimeout(() => { console.log(name) if (callback) { callback() } }, 1000) } print("a", function () { print("b", function () { print("c", function () { print("d") }) }) })
當(dāng)我們想按順序依次打印a、b、c、d時(shí),代碼就變成上面的樣子,可以看到,我們的代碼形成四層嵌套,如果還要加回調(diào)函數(shù)就要繼續(xù)嵌套,這樣嵌套會(huì)越寫越深,越來越難以維護(hù),此時(shí)我們就必須考慮用新的技術(shù)去改進(jìn),es6的Promise函數(shù)應(yīng)運(yùn)而生,接下來讓我們看Promise函數(shù)是如何改進(jìn)這個(gè)問題的。
Promisefunction print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve() }, 1000) }) } print("a").then(() => { return print("b") }) .then(() => { return print("c") }) .then(() => { return print("d") })
和之前用回調(diào)函數(shù)的形式相比,Promise函數(shù)寫法更加清晰,由回調(diào)函數(shù)的嵌套調(diào)用變成了鏈?zhǔn)秸{(diào)用,但是Promise也有一個(gè)很嚴(yán)重的問題就是代碼冗余,原來的任務(wù)被Promise包裝了一下,不管什么操作都是放在then函數(shù)里面,導(dǎo)致代碼的語(yǔ)以變差,有什么更好的解決辦法呢?如果您對(duì)Promise函數(shù)還想有更深入的了解,可以去看阮一峰老師es6入門
Async在正式使用異步函數(shù)之前,先簡(jiǎn)單的介紹一下它的用法,async通常與await一起使用,async函數(shù)返回一個(gè)Promise對(duì)象,可以使用then方法添加回調(diào)函數(shù)。當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到觸發(fā)的異步操作完成,再接著執(zhí)行函數(shù)體后面的語(yǔ)句。做了簡(jiǎn)單的介紹后,接下來,我們來async函數(shù)是怎么對(duì)Promise調(diào)用優(yōu)化的。看下面的例子:
function print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve() }, 1000) }) } async function test () { await print("a") await print("b") await print("c") await print("d") } test()
async函數(shù)來處理之前的問題,代碼就是上面的這個(gè)例子中所展示的樣子,是不是感覺代碼瞬間清晰了,而且代碼更加好理解了,再仔細(xì)思考一下使用async異步函數(shù)就很完美了嗎?其實(shí)async異步函數(shù)也有其固有的問題,接下來我們就看看async異步函數(shù)還有什么問題需要解決。
錯(cuò)誤捕獲異步函數(shù)第一個(gè)需要解決的問題就是錯(cuò)誤捕獲的問題,讓我們看看一般情況下async異步函數(shù)是怎么做錯(cuò)誤捕獲的,來看一個(gè)例子:
function print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve() }, 1000) }) } async function test () { try { await print("a") } catch (err) { console.log(err) } } test()
當(dāng)使用上述形式的try,catch進(jìn)行錯(cuò)誤捕獲的時(shí)候,是不是覺得代碼和使用Promise函數(shù)時(shí)一樣啰嗦,那有沒有好的解決辦法呢?讓我們來看另外一個(gè)例子:
function print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve("a") }, 1000) }) } async function test () { let [ err, result ] = await to(print("a")) if (err) throw err return result } test()
to.js:
function to(promise, errorExt) { return promise .then(function (data) { return [null, data]; }) .catch(function (err) { if (errorExt) { Object.assign(err, errorExt); } return [err, undefined]; }); } export { to }; export default to;
上述例子中,將async異步函數(shù)的錯(cuò)誤處理封裝到了一個(gè)to.js中,這里面其實(shí)只有一個(gè)簡(jiǎn)單方法,傳入一個(gè)Promise對(duì)象,對(duì)Promise對(duì)象進(jìn)行錯(cuò)誤捕獲返回值,用解構(gòu)的形式獲取返回值和錯(cuò)誤,這樣就不需要反復(fù)寫try catche做錯(cuò)誤捕獲了。to.js是一個(gè)開源庫(kù)
異步陷阱什么是異步陷阱呢?在使用async異步函數(shù)的時(shí)候,多個(gè)異步操作是可以同時(shí)執(zhí)行,但是有await命令變成了繼發(fā)的形式了,即必須等待前一個(gè)執(zhí)行完了后一個(gè)才能執(zhí)行,還是之前的例子:
function print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve() }, 1000) }) } async function test () { await print("a") await print("b") await print("c") await print("d") } test()
假設(shè)await print("a")、await print("b")、await print("c")、await print("d")這四個(gè)操作并沒有先后的邏輯關(guān)系,可以同時(shí)執(zhí)行,那么按照上面的寫法就會(huì)導(dǎo)致前一個(gè)執(zhí)行完再執(zhí)行下一個(gè),整個(gè)執(zhí)行過程中的等待時(shí)間會(huì)有4s,但是同時(shí)執(zhí)行的等待時(shí)間就只有1s,這是在使用async異步函數(shù)會(huì)經(jīng)常忽略的一個(gè)問題,那么怎么解決呢?介紹一個(gè)我經(jīng)常使用的辦法,看例子:
function print(name) { return new Promise((resolve, reject) => { setTimeout(() => { console.log(name) resolve("a") }, 1000) }) } async function test () { Promise.all([print("a"), print("b"), print("c"), print("d")]) } test()
其實(shí)解決辦法很簡(jiǎn)單就是通過Promise.all()方法,將所有異步操作作為參數(shù)數(shù)組傳入,這樣print("a")、print("b")、print("c")、print("d")這四個(gè)異步操作就可以并發(fā)執(zhí)行了。
總結(jié)這篇文章簡(jiǎn)單的介紹了一些常用的異步編程的方法,如果有錯(cuò)誤或不嚴(yán)謹(jǐn)?shù)牡胤剑瑲g迎批評(píng)指正,如果喜歡,歡迎點(diǎn)贊收藏。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/98835.html
摘要:學(xué)習(xí)開發(fā),無論是前端開發(fā)還是都避免不了要接觸異步編程這個(gè)問題就和其它大多數(shù)以多線程同步為主的編程語(yǔ)言不同的主要設(shè)計(jì)是單線程異步模型。由于異步編程可以實(shí)現(xiàn)非阻塞的調(diào)用效果,引入異步編程自然就是順理成章的事情了。 學(xué)習(xí)js開發(fā),無論是前端開發(fā)還是node.js,都避免不了要接觸異步編程這個(gè)問題,就和其它大多數(shù)以多線程同步為主的編程語(yǔ)言不同,js的主要設(shè)計(jì)是單線程異步模型。正因?yàn)閖s天生的與...
摘要:異步編程在傳統(tǒng)編程實(shí)踐中,大多數(shù)操作都是同步發(fā)生的。中的異步編程異步是一種輸入輸出處理的形式,它允許在傳輸完成之前,其它處理能繼續(xù)進(jìn)行。 本文轉(zhuǎn)載自:眾成翻譯譯者:網(wǎng)絡(luò)埋伏紀(jì)事鏈接:http://www.zcfy.cc/article/1759原文:https://blog.risingstack.com/node-hero-async-programming-in-node-js/ ...
摘要:四異步編程解決方案模式模式一定程度上緩解了嵌套回調(diào)的問題,只會(huì)處在未完成完成態(tài)失敗態(tài)中的一種,只會(huì)從未完成轉(zhuǎn)化為完成態(tài)或者失敗態(tài),不能逆轉(zhuǎn)。 一、從一個(gè)簡(jiǎn)單的案例開始 fs.readdir(path.join(__dirname, ./index.js), (err, files) => { files.foreach((filename, index) => { ...
摘要:下面我將介紹的基本用法以及如何在異步編程中使用它們。在沒有發(fā)布之前,作為異步編程主力軍的回調(diào)函數(shù)一直被人詬病,其原因有太多比如回調(diào)地獄代碼執(zhí)行順序難以追蹤后期因代碼變得十分復(fù)雜導(dǎo)致無法維護(hù)和更新等,而的出現(xiàn)在很大程度上改變了之前的窘境。 前言 自己著手準(zhǔn)備寫這篇文章的初衷是覺得如果想要更深入的理解 JS,異步編程則是必須要跨過的一道坎。由于這里面涉及到的東西很多也很廣,在初學(xué) JS 的...
摘要:為了降低異步編程的復(fù)雜性,所以。難理解請(qǐng)參考的誤區(qū)以及實(shí)踐異步編程的模式異步編程的種方法 異步編程 javascript異步編程, web2.0時(shí)代比較熱門的編程方式,我們平時(shí)碼的時(shí)候也或多或少用到,最典型的就是異步ajax,發(fā)送異步請(qǐng)求,綁定回調(diào)函數(shù),請(qǐng)求響應(yīng)之后調(diào)用指定的回調(diào)函數(shù),沒有阻塞其他代碼的執(zhí)行。還有像setTimeout方法同樣也是異步執(zhí)行回調(diào)的方法。 如果對(duì)異步編程...
閱讀 1995·2021-11-15 18:09
閱讀 889·2021-09-06 15:13
閱讀 2636·2021-08-23 09:43
閱讀 2016·2019-08-30 15:54
閱讀 2209·2019-08-30 13:56
閱讀 2476·2019-08-26 11:31
閱讀 3070·2019-08-26 10:56
閱讀 685·2019-08-26 10:28