js中異步函數(shù)async function變同步函數(shù)的簡(jiǎn)單入門
js異步函數(shù)async function變同步函數(shù)入門
js 中異步函數(shù)之所以特別,一個(gè)重要的原因就是它執(zhí)行完成的時(shí)間、耗費(fèi)的時(shí)間靠人的主觀是不得而知的。
所以不能靠設(shè)置定時(shí)函數(shù)來(lái)讓上一個(gè)程式完成之后來(lái)進(jìn)行下一個(gè)函數(shù)。
接上次的文章:js 異步獲取到的數(shù)據(jù) 到底能不能 賦值給一個(gè)全局變量
所以 promise 就突出了它的作用,目前程式執(zhí)行在那個(gè)階段 結(jié)果是什么 promise 知道。新建一個(gè) promise 對(duì)象。
new Promise(function (resolve, reject) { // 要做的事情... });
嘗試一個(gè) ajix 請(qǐng)求
<script> var goodsInfo = {}; $(document).ready(function(){ // 使用Promise new Promise(function (resolve,reject) { $.ajax({url:"https://api-hmugo- web.itheima.net/api/public/v1/home/catitems",success:function(result){ goodsInfo = result; resolve(goodsInfo); console.log(goodsInfo); }}); }).then(function () { console.log(goodsInfo); }) console.log(1); console.log(goodsInfo); }); </script>
看是不是在 .then() 中得到了經(jīng)過(guò)ajax請(qǐng)賦值后的全局變量 goodsInfo 的值,如果再有什么對(duì) goodsInfo 的操作,在 .then 中進(jìn)行即可。
ajax在項(xiàng)目會(huì)頻繁使用,將其封裝成一個(gè)函數(shù)會(huì)更方便
<script> var goodsInfo = {}; $(document).ready(function(){ // 封裝一個(gè) promise 函數(shù),在promiise對(duì)象前面多加了一個(gè)return function promiseFun (url){ return new Promise(function (resolve,reject) { $.ajax({url:url,success:function(result){ goodsInfo = result; resolve(goodsInfo); console.log(goodsInfo); }}); }) } // 調(diào)用函數(shù) promiseFun("https://api-hmugo-web.itheima.net/api/public/v1/home/catitems").then(function () { console.log(goodsInfo); }) console.log(1); console.log(goodsInfo); }); </script>
結(jié)果依然一樣。調(diào)用的時(shí)候是不是又簡(jiǎn)約一點(diǎn)。 async function 感覺(jué)是又進(jìn)了異步
// 定義規(guī)則 async function asyncFunc() { // await 后面必須是定義過(guò)的 promise function await myfunction(); await youfunction(); await shefunction(); somefunction(); xxxxxx; } asyncFunc();
<script> var goodsInfo = {}; var data ={}; $(document).ready(function(){ // 先定義一個(gè) promise function function promiseFun (url){ return new Promise(function (resolve,reject) { $.ajax({url:url,success:function(result){ goodsInfo = result; resolve(goodsInfo); console.log(goodsInfo); }}); }) } // 在定義一個(gè) asyns function async function asyncFuunc(){ // 看這里面的代碼執(zhí)行順序是不是跟同步函數(shù)簡(jiǎn)直一模一樣 await promiseFun("https://api-hmugo-web.itheima.net/api/public/v1/home/catitems"); console.log(goodsInfo); data=goodsInfo; console.log(data) console.log(2); } // 調(diào)用 asyns 函數(shù) asyncFuunc(); console.log(1); console.log(goodsInfo); }); </script>
異步函數(shù)(async/await)
異步函數(shù)
異步函數(shù),也稱為"async/await" (語(yǔ)法關(guān)鍵字),是ES6 期約模式在ECMAScript 函數(shù)中的應(yīng)用。async/await 是ES8 規(guī)范新增的。為了解決利用異步結(jié)構(gòu)組織代碼的問(wèn)題。
- async
async 關(guān)鍵字用于聲明異步函數(shù)。這個(gè)關(guān)鍵字可以用在函數(shù)聲明、函數(shù)表達(dá)式、箭頭函數(shù)和方法上:
? ? async function foo() {} ?? ? ? let bar = async function() {}; ? ? ? let baz = async() => {}; ?? ? ? class Qux { ?? ? ? ? ? async qux() {} ?? ? ? }
異步函數(shù)如果使用return 返回了值(沒(méi)有return 則會(huì)返回undefined),這個(gè)值會(huì)被Promise.resolve() 包裝成一個(gè)期約對(duì)象。
? ? async function foo(){ ? ? ? ? console.log(1) ? ? } ? ? console.log(foo()); //promise {<fulfilled>:undefined} ? ? foo().then(console.log) //undefined ? ? console.log(2) ? ? //1 ? ? //2 ? ? //undefined
- await
await 關(guān)鍵字可以暫停異步函數(shù)代碼的執(zhí)行,等待期約解決。await 會(huì)暫停執(zhí)行異步函數(shù)后面的代碼,讓出JS 運(yùn)行時(shí)的執(zhí)行線程。這個(gè)行為與生成器函數(shù)中的yield 關(guān)鍵字是一樣的。await 關(guān)鍵字同樣是嘗試 “解包” 對(duì)象的值,然后將這個(gè)值傳給表達(dá)式,再異步恢復(fù)異步函數(shù)的執(zhí)行。
await 關(guān)鍵字必須在異步函數(shù)中使用;異步函數(shù)的特質(zhì)不會(huì)擴(kuò)展到嵌套函數(shù)。否則會(huì)拋出SyntaxError;
async function foo(){ ? ? await Promise.resolve(3); } foo();
async/await 中真正起作用的是await。異步函數(shù)如果不包含await 關(guān)鍵字,其執(zhí)行基本上跟普通函數(shù)沒(méi)什么區(qū)別。
JavaScript 運(yùn)行時(shí)在碰到await 關(guān)鍵字時(shí),會(huì)記錄在哪里暫停執(zhí)行。等到await 右邊的值可用了,js運(yùn)行時(shí)會(huì)向消息隊(duì)列中推送一個(gè)任務(wù),這個(gè)任務(wù)會(huì)恢復(fù)異步函數(shù)的執(zhí)行。
因此,即使await 后面跟著一個(gè)立即可用的值,函數(shù)的其他部分也會(huì)被異步求值。
? ? async function foo() {? ? ? ? ? console.log(2); ?? ? ? ? ? await null; ? ? ? ? console.log(4); ? ? ? } ?? ? ? console.log(1); ? ? foo(); ? ? console.log(3); ? ? // 1 ? ? // 2 ? ? // 3 ? ? // 4 ? ?? ? ? 控制臺(tái)中輸出結(jié)果的順序很好地解釋了運(yùn)行時(shí)的工作過(guò)程: ? ? (1)打印1; ? ? (2)調(diào)用異步函數(shù)foo(); ? ? (3)(在foo()中)打印2; ? ? (4)(在foo()中)await關(guān)鍵字暫停執(zhí)行,為立即可用的值null向消息隊(duì)列中添加一個(gè)任務(wù); ? ? (5)foo()退出; ? ? (6)打印3; ? ? (7)同步線程的代碼執(zhí)行完畢; ? ? (8)JavaScript運(yùn)行時(shí)從消息隊(duì)列中取出任務(wù),恢復(fù)異步函數(shù)執(zhí)行; ? ? (9)(在foo()中)恢復(fù)執(zhí)行,await取得null值(這里并沒(méi)有使用); ? ? (10)(在foo()中)打印4; ? ? (11)foo()返回。
異步函數(shù)策略
- 實(shí)現(xiàn)sleep()
很多人在剛開(kāi)始學(xué)習(xí)JavaScript時(shí),想找到一個(gè)類似Java中Thread.sleep()之類的函數(shù),好在程序中加入非阻塞的暫停。以前,這個(gè)需求基本上都通過(guò)setTimeout()利用JavaScript運(yùn)行時(shí)的行為來(lái)實(shí)現(xiàn)的。
有了異步函數(shù)之后,就不一樣了。一個(gè)簡(jiǎn)單的箭頭函數(shù)就可以實(shí)現(xiàn)sleep():
?async function sleep(delay) { ? ? ? ? return new Promise((resolve) => setTimeout(resolve, delay)); ? ? } ? ? async function sleepfoo(){ ? ? ? ? const t0 = Date.now(); ? ? ? ? await sleep(2000); ? ? ? ? const t1 = Date.now(); ? ? ? ? console.log(t1 - t0); ? ? } ? ? sleepfoo() ? ? //2002 ?任務(wù)隊(duì)列執(zhí)行,時(shí)間不一定
- 利用平行執(zhí)行
- 串行執(zhí)行期約
- 棧追蹤與內(nèi)存管理
注意:
異步函數(shù)是將期約應(yīng)用于JavaScript函數(shù)的結(jié)果。異步函數(shù)可以暫停執(zhí)行,而不阻塞主線程。無(wú)論是編寫基于期約的代碼,還是組織串行或平行執(zhí)行的異步代碼,使用異步函數(shù)都非常得心應(yīng)手。異步函數(shù)可以說(shuō)是現(xiàn)代JavaScript工具箱中最重要的工具之一。
總結(jié)
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
詳解ES6 Fetch API HTTP請(qǐng)求實(shí)用指南
本次將介紹如何使用Fetch API(ES6 +)對(duì)REST API的 HTTP請(qǐng)求,還有一些示例提供給大家便于大家理解。具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-11-11JavaScript實(shí)現(xiàn)顯示和隱藏圖片
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)顯示和隱藏圖片,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04JS統(tǒng)計(jì)Flash被網(wǎng)友點(diǎn)擊過(guò)的代碼
JS統(tǒng)計(jì)Flash被網(wǎng)友點(diǎn)擊過(guò)的代碼...2007-05-05layui.use模塊外部使用其內(nèi)部定義的js封裝函數(shù)方法
今天小編就為大家分享一篇layui.use模塊外部使用其內(nèi)部定義的js封裝函數(shù)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09JavaScript設(shè)計(jì)模式之建造者模式介紹
這篇文章主要介紹了JavaScript設(shè)計(jì)模式之建造者模式介紹,將一個(gè)復(fù)雜對(duì)象的構(gòu)造與它的表示相分離,使同樣的創(chuàng)建過(guò)程可有不同的表示,這就叫做建造者模式,需要的朋友可以參考下2014-12-12在iframe里的頁(yè)面編寫js,實(shí)現(xiàn)在父窗口上創(chuàng)建動(dòng)畫效果展開(kāi)和收縮的div(不變動(dòng)iframe父窗口代碼)
在iframe里的頁(yè)面編寫js,實(shí)現(xiàn)在父窗口上創(chuàng)建動(dòng)畫效果展開(kāi)和收縮的div(不變動(dòng)iframe父窗口代碼)2011-12-12