javascript
JavaScript异步
?JavaScript異步類型
- 延遲類型:setTimeout、setInterval、setImmediate
- 監(jiān)聽事件:監(jiān)聽new Image加載狀態(tài)、監(jiān)聽script加載狀態(tài)、監(jiān)聽iframe加載狀態(tài)、Message
- 帶有異步功能類型: Promise、ajax、Worker、async/await
JavaScript常用異步編程
Promise
? Promise有幾個(gè)特點(diǎn):
? 方法:
- 原型方法 all race reject resolve
- 對象方法 then catch finally(ES9)
觀察then和catch的用法:
- 在多次then后最后跟一個(gè)catch,可以捕獲所有的異常
all和rece的用法:
- all接收一個(gè)promise對象列表.在所有異步操作執(zhí)行完且全部成功的時(shí)候才執(zhí)行then回調(diào),只要有一個(gè)失敗,就執(zhí)行catch回調(diào)(只對第一個(gè)失敗的promise對象執(zhí)行)。
- race也接收一個(gè)promise對象列表,不同的是,哪個(gè)最先執(zhí)行完,對應(yīng)的那個(gè)對象就執(zhí)行then或catch方法(then或catch只執(zhí)行一次)。
Generator
Generator是什么?叫做生成器,通過function*關(guān)鍵字來定義的函數(shù)稱之為生成器函數(shù)(generator function),與Python的語法一模一樣
生成器有3個(gè)方法,都有一樣的返回值{value,done}
- .next(value)? ?value為向生成器傳遞的值。
- .return(value) value為需要返回的值。該方法返回給定的值并結(jié)束生成器。
- .throw(exception)? exception用于拋出的異常。該方法用來向生成器拋出異常,并恢復(fù)生成器的執(zhí)行。
生成器的作用:
可以和 Promise 組合使用。減少代碼量,寫起來更方便。在沒有Generator時(shí),寫Promise會需要很多的then,每個(gè)then內(nèi)都有不同的處理邏輯。現(xiàn)在,我們將所有的邏輯寫進(jìn)一個(gè)生成器函數(shù)(或者在生成器函數(shù)內(nèi)用yield 進(jìn)行函數(shù)調(diào)用),Promise的每個(gè)then內(nèi)調(diào)用同一個(gè)函數(shù)即可。
定義生成器:
function add(a,b) {console.log("+");return a+b; } function cut(a,b) {console.log("-");return a-b; } function mul(a,b) {console.log("*");return a*b; } function division(a,b) {console.log("/");return a/b; } function* compute(a, b) {yield add(a,b);yield cut(a,b);let value = yield mul(a,b);console.log("value",value); // 第三次調(diào)用.next()時(shí)無法為value賦值,需要第四次調(diào)用才能為其賦值yield mul(a,b);yield division(a,b); }使用生成器:
// 執(zhí)行一下這個(gè)函數(shù)得到 Generator 實(shí)例,調(diào)用next()方法執(zhí)行,遇到y(tǒng)ield暫停 let generator = compute(4, 2);function promise() {return new Promise((resolve, reject) => {let res = generator.next();if(res.value > 5){resolve("OK");}else{reject("小于5")}}); }let proObj = promise(); proObj.then((data)=>{console.log(data);let res = generator.next();console.log("Promise res1",res); }).then((data)=>{let res = generator.next();// let res = generator.return();console.log("Promise res2",res); }).then((data)=>{let res = generator.next("qwe"); // 第四次next()時(shí),向生成器傳數(shù)據(jù)console.log("Promise res3",res) }).catch((err)=>{console.log("出錯(cuò)",err); });async/await
優(yōu)點(diǎn):簡潔,節(jié)約了不少代碼
- 被async修飾的函數(shù),總會返回一個(gè)Promise對象。如果代碼中返回值不是promise對象,它會將其包裝成promise對象的resolved值
- await只能在async函數(shù)內(nèi)使用。它是一個(gè)操作符,等待一個(gè)函數(shù)或表達(dá)式。經(jīng)過該操作符處理后,輸出一個(gè)值。
如果在異步函數(shù)中,每個(gè)任務(wù)都需要上個(gè)任務(wù)的返回結(jié)果,可以這么做:
function takeLongTime(n) {return new Promise((resolve,reject) => {setTimeout(() => {resolve(n + 200)}, n);}); }function step1(n) {console.log(`step1 with ${n}`);return takeLongTime(n); }function step2(m, n) {console.log(`step2 with ${m} and ${n}`);return takeLongTime(m + n); }function step3(k, m, n) {console.log(`step3 with ${k}, ${m} and ${n}`);return takeLongTime(k + m + n); }async function doIt() {console.time("doIt");const time1 = 300;const time2 = await step1(time1);const time3 = await step2(time1, time2);const result = await step3(time1, time2, time3);console.log(`result is ${result}`);console.timeEnd("doIt"); } doIt();如果這幾個(gè)任務(wù)沒有關(guān)聯(lián),可以這樣做:
async function doIt() { // 函數(shù)執(zhí)行耗時(shí)2100msconsole.time("doIt");await step1(300).catch((err)=>{console.log(err)}); // 異常處理await step1(800);await step1(1000);console.timeEnd("doIt"); } doIt();當(dāng)然,最好這樣做:
async function doIt() { // 函數(shù)執(zhí)行耗時(shí)1000msconsole.time("doIt");const time1Pro = step1(300);const time2Pro = step1(800);const time3Pro = step1(1000);await time1Pro;await time2Pro;await time3Pro;console.timeEnd("doIt"); } doIt();注意:
- 怎么體現(xiàn)更好地協(xié)同?它替代了then catch的寫法。使得等待promise值的操作更優(yōu)雅,更容易閱讀和書寫。
- 這需要精準(zhǔn)理解await。它在等待的時(shí)候并沒有阻塞程序,此函數(shù)也不占用CPU資源,使得整個(gè)函數(shù)做到了異步執(zhí)行。
- 【錯(cuò)誤想法】這樣想沒錯(cuò),但是沒必要。因?yàn)樗麄円呀?jīng)存在于異步函數(shù)內(nèi)了,所有的操作已經(jīng)是異步的。在同樣的環(huán)境情景下,底層執(zhí)行的效率是相同的,并不見得因?yàn)锳和B之間互相異步而提高效率。
- 【正確想法】這樣想是有必要的。參照兩個(gè)doIt(),調(diào)用的函數(shù)返回promise對象,前者是依次生成promise對象(依次執(zhí)行任務(wù)),依次等待返回結(jié)果。等待總時(shí)長取決于所有任務(wù)執(zhí)行時(shí)間之和。后者則是同時(shí)生成promise對象(同時(shí)執(zhí)行任務(wù)),依次等待。等待總時(shí)長取決于耗時(shí)最長的任務(wù)。后者的CPU運(yùn)用率更高。
?
轉(zhuǎn)載于:https://www.cnblogs.com/V587Chinese/p/11437051.html
總結(jié)
以上是生活随笔為你收集整理的JavaScript异步的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MPS和MRP之间有什么样的关系呢
- 下一篇: 数据库表操作、数据类型及完整性约束