成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

Javascript異步編程之你真的懂Promise嗎

瀏覽:4日期:2023-09-30 16:41:50
前言

在異步編程中,Promise 扮演了舉足輕重的角色,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合理和更強(qiáng)大??赡苡行┬』锇闀?huì)有這樣的疑問:2020年了,怎么還在談?wù)揚(yáng)romise?事實(shí)上,有些朋友對(duì)于這個(gè)幾乎每天都在打交道的“老朋友”,貌似全懂,但稍加深入就可能疑問百出,本文帶大家深入理解這個(gè)熟悉的陌生人—— Promise.

基本用法語(yǔ)法

new Promise( function(resolve, reject) {...} /* executor */ ) 構(gòu)建 Promise 對(duì)象時(shí),需要傳入一個(gè) executor函數(shù),主要業(yè)務(wù)流程都在 executor 函數(shù)中執(zhí)行。 Promise構(gòu)造函數(shù)執(zhí)行時(shí)立即調(diào)用executor 函數(shù), resolve 和 reject 兩個(gè)函數(shù)作為參數(shù)傳遞給executor,resolve 和 reject 函數(shù)被調(diào)用時(shí),分別將promise的狀態(tài)改為fulfilled(完成)或rejected(失?。?。一旦狀態(tài)改變,就不會(huì)再變,任何時(shí)候都可以得到這個(gè)結(jié)果。 在 executor 函數(shù)中調(diào)用 resolve 函數(shù)后,會(huì)觸發(fā) promise.then 設(shè)置的回調(diào)函數(shù);而調(diào)用 reject 函數(shù)后,會(huì)觸發(fā) promise.catch 設(shè)置的回調(diào)函數(shù)。

Javascript異步編程之你真的懂Promise嗎

值得注意的是,Promise 是用來管理異步編程的,它本身不是異步的,new Promise的時(shí)候會(huì)立即把executor函數(shù)執(zhí)行,只不過我們一般會(huì)在executor函數(shù)中處理一個(gè)異步操作。比如下面代碼中,一開始是會(huì)先打印出2。

let p1 = new Promise(()=>{ setTimeout(()=>{ console.log(1) },1000) console.log(2) })console.log(3) // 2 3 1

Promise 采用了回調(diào)函數(shù)延遲綁定技術(shù),在執(zhí)行 resolve 函數(shù)的時(shí)候,回調(diào)函數(shù)還沒有綁定,那么只能推遲回調(diào)函數(shù)的執(zhí)行。這具體是啥意思呢?我們先來看下面的例子:

let p1 = new Promise((resolve,reject)=>{ console.log(1); resolve(’浪里行舟’) console.log(2)})// then:設(shè)置成功或者失敗后處理的方法p1.then(result=>{ //p1延遲綁定回調(diào)函數(shù) console.log(’成功 ’+result)},reason=>{ console.log(’失敗 ’+reason)})console.log(3)// 1// 2// 3// 成功 浪里行舟

new Promise的時(shí)候先執(zhí)行executor函數(shù),打印出 1、2,Promise在執(zhí)行resolve時(shí),觸發(fā)微任務(wù),還是繼續(xù)往下執(zhí)行同步任務(wù),

執(zhí)行p1.then時(shí),存儲(chǔ)起來兩個(gè)函數(shù)(此時(shí)這兩個(gè)函數(shù)還沒有執(zhí)行),然后打印出3,此時(shí)同步任務(wù)執(zhí)行完成,最后執(zhí)行剛剛那個(gè)微任務(wù),從而執(zhí)行.then中成功的方法。

錯(cuò)誤處理

Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì),會(huì)一直向后傳遞,直到被 onReject 函數(shù)處理或 catch 語(yǔ)句捕獲為止。具備了這樣“冒泡”的特性后,就不需要在每個(gè) Promise 對(duì)象中單獨(dú)捕獲異常了。

要遇到一個(gè)then,要執(zhí)行成功或者失敗的方法,但如果此方法并沒有在當(dāng)前then中被定義,則順延到下一個(gè)對(duì)應(yīng)的函數(shù)

function executor (resolve, reject) { let rand = Math.random() console.log(1) console.log(rand) if (rand > 0.5) { resolve() } else { reject() }}var p0 = new Promise(executor)var p1 = p0.then((value) => { console.log(’succeed-1’) return new Promise(executor)})var p2 = p1.then((value) => { console.log(’succeed-2’) return new Promise(executor)})p2.catch((error) => { console.log(’error’, error)})console.log(2)

這段代碼有三個(gè) Promise 對(duì)象:p0~p2。無論哪個(gè)對(duì)象里面拋出異常,都可以通過最后一個(gè)對(duì)象 p2.catch 來捕獲異常,通過這種方式可以將所有 Promise 對(duì)象的錯(cuò)誤合并到一個(gè)函數(shù)來處理,這樣就解決了每個(gè)任務(wù)都需要單獨(dú)處理異常的問題。

通過這種方式,我們就消滅了嵌套調(diào)用和頻繁的錯(cuò)誤處理,這樣使得我們寫出來的代碼更加優(yōu)雅,更加符合人的線性思維。

Promise鏈?zhǔn)秸{(diào)用

我們都知道可以把多個(gè)Promise連接到一起來表示一系列異步驟。這種方式可以實(shí)現(xiàn)的關(guān)鍵在于以下兩個(gè)Promise 固有行為特性:

每次你對(duì)Promise調(diào)用then,它都會(huì)創(chuàng)建并返回一個(gè)新的Promise,我們可以將其鏈接起來; 不管從then調(diào)用的完成回調(diào)(第一個(gè)參數(shù))返回的值是什么,它都會(huì)被自動(dòng)設(shè)置為被鏈接Promise(第一點(diǎn)中的)的完成。

先通過下面的例子,來解釋一下剛剛這段話是什么意思,然后詳細(xì)介紹下鏈?zhǔn)秸{(diào)用的執(zhí)行流程

let p1=new Promise((resolve,reject)=>{ resolve(100) // 決定了下個(gè)then中成功方法會(huì)被執(zhí)行})// 連接p1let p2=p1.then(result=>{ console.log(’成功1 ’+result) return Promise.reject(1) // 返回一個(gè)新的Promise實(shí)例,決定了當(dāng)前實(shí)例是失敗的,所以決定下一個(gè)then中失敗方法會(huì)被執(zhí)行},reason=>{ console.log(’失敗1 ’+reason) return 200})// 連接p2 let p3=p2.then(result=>{ console.log(’成功2 ’+result)},reason=>{ console.log(’失敗2 ’+reason)})// 成功1 100// 失敗2 1

我們通過返回 Promise.reject(1) ,完成了第一個(gè)調(diào)用then創(chuàng)建并返回的promise p2。p2的then調(diào)用在運(yùn)行時(shí)會(huì)從return Promise.reject(1) 語(yǔ)句接受完成值。當(dāng)然,p2.then又創(chuàng)建了另一個(gè)新的promise,可以用變量p3存儲(chǔ)。

new Promise出來的實(shí)例,成功或者失敗,取決于executor函數(shù)執(zhí)行的時(shí)候,執(zhí)行的是resolve還是reject決定的,或executor函數(shù)執(zhí)行發(fā)生異常錯(cuò)誤,這兩種情況都會(huì)把實(shí)例狀態(tài)改為失敗的。

p2執(zhí)行then返回的新實(shí)例的狀態(tài),決定下一個(gè)then中哪一個(gè)方法會(huì)被執(zhí)行,有以下幾種情況:

不論是成功的方法執(zhí)行,還是失敗的方法執(zhí)行(then中的兩個(gè)方法),凡是執(zhí)行拋出了異常,則都會(huì)把實(shí)例的狀態(tài)改為失敗。 方法中如果返回一個(gè)新的Promise實(shí)例(比如上例中的Promise.reject(1)),返回這個(gè)實(shí)例的結(jié)果是成功還是失敗,也決定了當(dāng)前實(shí)例是成功還是失敗。 剩下的情況基本上都是讓實(shí)例變?yōu)槌晒Φ臓顟B(tài),上一個(gè)then中方法返回的結(jié)果會(huì)傳遞到下一個(gè)then的方法中。

我們?cè)賮砜磦€(gè)例子

new Promise(resolve=>{ resolve(a) // 報(bào)錯(cuò) // 這個(gè)executor函數(shù)執(zhí)行發(fā)生異常錯(cuò)誤,決定下個(gè)then失敗方法會(huì)被執(zhí)行}).then(result=>{ console.log(`成功:${result}`) return result*10},reason=>{ console.log(`失敗:${reason}`)// 執(zhí)行這句時(shí)候,沒有發(fā)生異?;蛘叻祷匾粋€(gè)失敗的Promise實(shí)例,所以下個(gè)then成功方法會(huì)被執(zhí)行// 這里沒有return,最后會(huì)返回 undefined}).then(result=>{ console.log(`成功:${result}`)},reason=>{ console.log(`失敗:${reason}`)})// 失?。篟eferenceError: a is not defined// 成功:undefinedasync & await

從上面一些例子,我們可以看出,雖然使用 Promise 能很好地解決回調(diào)地獄的問題,但是這種方式充滿了 Promise 的 then() 方法,如果處理流程比較復(fù)雜的話,那么整段代碼將充斥著 then,語(yǔ)義化不明顯,代碼不能很好地表示執(zhí)行流程。

ES7中新增的異步編程方法,async/await的實(shí)現(xiàn)是基于 Promise的,簡(jiǎn)單而言就是async 函數(shù)就是返回Promise對(duì)象,是generator的語(yǔ)法糖。很多人認(rèn)為async/await是異步操作的終極解決方案:

語(yǔ)法簡(jiǎn)潔,更像是同步代碼,也更符合普通的閱讀習(xí)慣; 改進(jìn)js中異步操作串行執(zhí)行的代碼組織方式,減少callback的嵌套; Promise中不能自定義使用try/catch進(jìn)行錯(cuò)誤捕獲,但是在Async/await中可以像處理同步代碼處理錯(cuò)誤。

不過也存在一些缺點(diǎn),因?yàn)?await 將異步代碼改造成了同步代碼,如果多個(gè)異步代碼沒有依賴性卻使用了 await 會(huì)導(dǎo)致性能上的降低。

async function test() { // 以下代碼沒有依賴性的話,完全可以使用 Promise.all 的方式 // 如果有依賴性的話,其實(shí)就是解決回調(diào)地獄的例子了 await fetch(url1) await fetch(url2) await fetch(url3)}

觀察下面這段代碼,你能判斷出打印出來的內(nèi)容是什么嗎?

let p1 = Promise.resolve(1)let p2 = new Promise(resolve => { setTimeout(() => { resolve(2) }, 1000)})async function fn() { console.log(1)// 當(dāng)代碼執(zhí)行到此行(先把此行),構(gòu)建一個(gè)異步的微任務(wù)// 等待promise返回結(jié)果,并且await下面的代碼也都被列到任務(wù)隊(duì)列中 let result1 = await p2 console.log(3) let result2 = await p1 console.log(4)}fn()console.log(2)// 1 2 3 4

如果 await 右側(cè)表達(dá)邏輯是個(gè) promise,await會(huì)等待這個(gè)promise的返回結(jié)果,只有返回的狀態(tài)是resolved情況,才會(huì)把結(jié)果返回,如果promise是失敗狀態(tài),則await不會(huì)接收其返回結(jié)果,await下面的代碼也不會(huì)在繼續(xù)執(zhí)行。

let p1 = Promise.reject(100)async function fn1() { let result = await p1 console.log(1) //這行代碼不會(huì)執(zhí)行}

我們?cè)賮砜吹辣容^復(fù)雜的題目:

console.log(1)setTimeout(()=>{console.log(2)},1000)async function fn(){ console.log(3) setTimeout(()=>{console.log(4)},20) return Promise.reject()}async function run(){ console.log(5) await fn() console.log(6)}run()//需要執(zhí)行150ms左右for(let i=0;i<90000000;i++){}setTimeout(()=>{ console.log(7) new Promise(resolve=>{console.log(8)resolve() }).then(()=>{console.log(9)})},0)console.log(10)// 1 5 3 10 4 7 8 9 2

做這道題之前,讀者需明白:

基于微任務(wù)的技術(shù)有 MutationObserver、Promise 以及以 Promise 為基礎(chǔ)開發(fā)出來的很多其他的技術(shù),本題中resolve()、await fn()都是微任務(wù)。 不管宏任務(wù)是否到達(dá)時(shí)間,以及放置的先后順序,每次主線程執(zhí)行棧為空的時(shí)候,引擎會(huì)優(yōu)先處理微任務(wù)隊(duì)列,處理完微任務(wù)隊(duì)列里的所有任務(wù),再去處理宏任務(wù)。

接下來,我們一步一步分析:

首先執(zhí)行同步代碼,輸出 1,遇見第一個(gè)setTimeout,將其回調(diào)放入任務(wù)隊(duì)列(宏任務(wù))當(dāng)中,繼續(xù)往下執(zhí)行 運(yùn)行run(),打印出 5,并往下執(zhí)行,遇見 await fn(),將其放入任務(wù)隊(duì)列(微任務(wù)) await fn() 當(dāng)前這一行代碼執(zhí)行時(shí),fn函數(shù)會(huì)立即執(zhí)行的,打印出3,遇見第二個(gè)setTimeout,將其回調(diào)放入任務(wù)隊(duì)列(宏任務(wù)),await fn() 下面的代碼需要等待返回Promise成功狀態(tài)才會(huì)執(zhí)行,所以6是不會(huì)被打印的。 繼續(xù)往下執(zhí)行,遇到for循環(huán)同步代碼,需要等150ms,雖然第二個(gè)setTimeout已經(jīng)到達(dá)時(shí)間,但不會(huì)執(zhí)行,遇見第三個(gè)setTimeout,將其回調(diào)放入任務(wù)隊(duì)列(宏任務(wù)),然后打印出10。值得注意的是,這個(gè)定時(shí)器 推遲時(shí)間0毫秒實(shí)際上達(dá)不到的。根據(jù)html5標(biāo)準(zhǔn),setTimeOut推遲執(zhí)行的時(shí)間,最少是4毫秒。 同步代碼執(zhí)行完畢,此時(shí)沒有微任務(wù),就去執(zhí)行宏任務(wù),上面提到已經(jīng)到點(diǎn)的setTimeout先執(zhí)行,打印出4 然后執(zhí)行下一個(gè)setTimeout的宏任務(wù),所以先打印出7,new Promise的時(shí)候會(huì)立即把executor函數(shù)執(zhí)行,打印出8,然后在執(zhí)行resolve時(shí),觸發(fā)微任務(wù),于是打印出9 最后執(zhí)行第一個(gè)setTimeout的宏任務(wù),打印出2常用的方法1、Promise.resolve()

Promise.resolve(value)方法返回一個(gè)以給定值解析后的Promise 對(duì)象。Promise.resolve()等價(jià)于下面的寫法:

Promise.resolve(’foo’)// 等價(jià)于new Promise(resolve => resolve(’foo’))

Promise.resolve方法的參數(shù)分成四種情況。

(1)參數(shù)是一個(gè) Promise 實(shí)例

如果參數(shù)是 Promise 實(shí)例,那么Promise.resolve將不做任何修改、原封不動(dòng)地返回這個(gè)實(shí)例。

const p1 = new Promise(function (resolve, reject) { setTimeout(() => reject(new Error(’fail’)), 3000)})const p2 = new Promise(function (resolve, reject) { setTimeout(() => resolve(p1), 1000)})p2 .then(result => console.log(result)) .catch(error => console.log(error))// Error: fail

上面代碼中,p1是一個(gè) Promise,3 秒之后變?yōu)閞ejected。p2的狀態(tài)在 1 秒之后改變,resolve方法返回的是p1。由于p2返回的是另一個(gè) Promise,導(dǎo)致p2自己的狀態(tài)無效了,由p1的狀態(tài)決定p2的狀態(tài)。所以,后面的then語(yǔ)句都變成針對(duì)后者(p1)。又過了 2 秒,p1變?yōu)閞ejected,導(dǎo)致觸發(fā)catch方法指定的回調(diào)函數(shù)。

(2)參數(shù)不是具有then方法的對(duì)象,或根本就不是對(duì)象

Promise.resolve('Success').then(function(value) { // Promise.resolve方法的參數(shù),會(huì)同時(shí)傳給回調(diào)函數(shù)。 console.log(value); // 'Success'}, function(value) { // 不會(huì)被調(diào)用});

(3)不帶有任何參數(shù)

Promise.resolve()方法允許調(diào)用時(shí)不帶參數(shù),直接返回一個(gè)resolved狀態(tài)的 Promise 對(duì)象。如果希望得到一個(gè) Promise 對(duì)象,比較方便的方法就是直接調(diào)用Promise.resolve()方法。

Promise.resolve().then(function () { console.log(’two’);});console.log(’one’);// one two

(4)參數(shù)是一個(gè)thenable對(duì)象

thenable對(duì)象指的是具有then方法的對(duì)象,Promise.resolve方法會(huì)將這個(gè)對(duì)象轉(zhuǎn)為 Promise 對(duì)象,然后就立即執(zhí)行thenable對(duì)象的then方法。

let thenable = { then: function(resolve, reject) { resolve(42); }};let p1 = Promise.resolve(thenable);p1.then(function(value) { console.log(value); // 42});2、Promise.reject()

Promise.reject()方法返回一個(gè)帶有拒絕原因的Promise對(duì)象。

new Promise((resolve,reject) => { reject(new Error('出錯(cuò)了'));});// 等價(jià)于 Promise.reject(new Error('出錯(cuò)了')); // 使用方法Promise.reject(new Error('BOOM!')).catch(error => { console.error(error);});

值得注意的是,調(diào)用resolve或reject以后,Promise 的使命就完成了,后繼操作應(yīng)該放到then方法里面,而不應(yīng)該直接寫在resolve或reject的后面。所以,最好在它們前面加上return語(yǔ)句,這樣就不會(huì)有意外。

new Promise((resolve, reject) => { return reject(1); // 后面的語(yǔ)句不會(huì)執(zhí)行 console.log(2);})3、Promise.all()

let p1 = Promise.resolve(1)let p2 = new Promise(resolve => { setTimeout(() => { resolve(2) }, 1000)})let p3 = Promise.resolve(3)Promise.all([p3, p2, p1]) .then(result => { // 返回的結(jié)果是按照Array中編寫實(shí)例的順序來 console.log(result) // [ 3, 2, 1 ] }) .catch(reason => { console.log('失敗:reason') })

Promise.all 生成并返回一個(gè)新的 Promise 對(duì)象,所以它可以使用 Promise 實(shí)例的所有方法。參數(shù)傳遞promise數(shù)組中所有的 Promise 對(duì)象都變?yōu)閞esolve的時(shí)候,該方法才會(huì)返回, 新創(chuàng)建的 Promise 則會(huì)使用這些 promise 的值。

如果參數(shù)中的任何一個(gè)promise為reject的話,則整個(gè)Promise.all調(diào)用會(huì)立即終止,并返回一個(gè)reject的新的 Promise 對(duì)象。

4、Promise.allSettled()

有時(shí)候,我們不關(guān)心異步操作的結(jié)果,只關(guān)心這些操作有沒有結(jié)束。這時(shí),ES2020 引入Promise.allSettled()方法就很有用。如果沒有這個(gè)方法,想要確保所有操作都結(jié)束,就很麻煩。Promise.all()方法無法做到這一點(diǎn)。

假如有這樣的場(chǎng)景:一個(gè)頁(yè)面有三個(gè)區(qū)域,分別對(duì)應(yīng)三個(gè)獨(dú)立的接口數(shù)據(jù),使用 Promise.all 來并發(fā)請(qǐng)求三個(gè)接口,如果其中任意一個(gè)接口出現(xiàn)異常,狀態(tài)是reject,這會(huì)導(dǎo)致頁(yè)面中該三個(gè)區(qū)域數(shù)據(jù)全都無法出來,顯然這種狀況我們是無法接受,Promise.allSettled的出現(xiàn)就可以解決這個(gè)痛點(diǎn):

Promise.allSettled([ Promise.reject({ code: 500, msg: ’服務(wù)異?!?}), Promise.resolve({ code: 200, list: [] }), Promise.resolve({ code: 200, list: [] })]).then(res => { console.log(res) /* 0: {status: 'rejected', reason: {…}} 1: {status: 'fulfilled', value: {…}} 2: {status: 'fulfilled', value: {…}} */ // 過濾掉 rejected 狀態(tài),盡可能多的保證頁(yè)面區(qū)域數(shù)據(jù)渲染 RenderContent( res.filter(el => { return el.status !== ’rejected’ }) )})

Promise.allSettled跟Promise.all類似, 其參數(shù)接受一個(gè)Promise的數(shù)組, 返回一個(gè)新的Promise,唯一的不同在于, 它不會(huì)進(jìn)行短路, 也就是說當(dāng)Promise全部處理完成后,我們可以拿到每個(gè)Promise的狀態(tài), 而不管是否處理成功。

5、Promise.race()

Promise.all()方法的效果是'誰(shuí)跑的慢,以誰(shuí)為準(zhǔn)執(zhí)行回調(diào)',那么相對(duì)的就有另一個(gè)方法'誰(shuí)跑的快,以誰(shuí)為準(zhǔn)執(zhí)行回調(diào)',這就是Promise.race()方法,這個(gè)詞本來就是賽跑的意思。race的用法與all一樣,接收一個(gè)promise對(duì)象數(shù)組為參數(shù)。

Promise.all在接收到的所有的對(duì)象promise都變?yōu)镕ulFilled或者Rejected狀態(tài)之后才會(huì)繼續(xù)進(jìn)行后面的處理,與之相對(duì)的是Promise.race只要有一個(gè)promise對(duì)象進(jìn)入FulFilled或者Rejected狀態(tài)的話,就會(huì)繼續(xù)進(jìn)行后面的處理。

// `delay`毫秒后執(zhí)行resolvefunction timerPromisefy(delay) { return new Promise(resolve => {setTimeout(() => { resolve(delay);}, delay); });}// 任何一個(gè)promise變?yōu)閞esolve或reject的話程序就停止運(yùn)行Promise.race([ timerPromisefy(1), timerPromisefy(32), timerPromisefy(64)]).then(function (value) { console.log(value); // => 1});

上面的代碼創(chuàng)建了3個(gè)promise對(duì)象,這些promise對(duì)象會(huì)分別在1ms、32ms 和 64ms后變?yōu)榇_定狀態(tài),即FulFilled,并且在第一個(gè)變?yōu)榇_定狀態(tài)的1ms后,.then注冊(cè)的回調(diào)函數(shù)就會(huì)被調(diào)用。

6、Promise.prototype.finally()

ES9 新增 finally() 方法返回一個(gè)Promise。在promise結(jié)束時(shí),無論結(jié)果是fulfilled或者是rejected,都會(huì)執(zhí)行指定的回調(diào)函數(shù)。這為在Promise是否成功完成后都需要執(zhí)行的代碼提供了一種方式。這避免了同樣的語(yǔ)句需要在then()和catch()中各寫一次的情況。

比如我們發(fā)送請(qǐng)求之前會(huì)出現(xiàn)一個(gè)loading,當(dāng)我們請(qǐng)求發(fā)送完成之后,不管請(qǐng)求有沒有出錯(cuò),我們都希望關(guān)掉這個(gè)loading。

this.loading = truerequest() .then((res) => { // do something }) .catch(() => { // log err }) .finally(() => { this.loading = false })

finally方法的回調(diào)函數(shù)不接受任何參數(shù),這表明,finally方法里面的操作,應(yīng)該是與狀態(tài)無關(guān)的,不依賴于 Promise 的執(zhí)行結(jié)果。

實(shí)際應(yīng)用

假設(shè)有這樣一個(gè)需求:紅燈 3s 亮一次,綠燈 1s 亮一次,黃燈 2s 亮一次;如何讓三個(gè)燈不斷交替重復(fù)亮燈?三個(gè)亮燈函數(shù)已經(jīng)存在:

function red() { console.log(’red’);}function green() { console.log(’green’);}function yellow() { console.log(’yellow’);}

這道題復(fù)雜的地方在于需要“交替重復(fù)”亮燈,而不是亮完一遍就結(jié)束的一錘子買賣,我們可以通過遞歸來實(shí)現(xiàn):

// 用 promise 實(shí)現(xiàn)let task = (timer, light) => { return new Promise((resolve, reject) => { setTimeout(() => { if (light === ’red’) {red() } if (light === ’green’) {green() } if (light === ’yellow’) {yellow() } resolve() }, timer); })}let step = () => { task(3000, ’red’) .then(() => task(1000, ’green’)) .then(() => task(2000, ’yellow’)) .then(step)}step()

同樣也可以通過async/await 的實(shí)現(xiàn):

// async/await 實(shí)現(xiàn)let step = async () => { await task(3000, ’red’) await task(1000, ’green’) await task(2000, ’yellow’) step()}step()

使用 async/await 可以實(shí)現(xiàn)用同步代碼的風(fēng)格來編寫異步代碼,毫無疑問,還是 async/await 的方案更加直觀,不過深入理解Promise 是掌握async/await的基礎(chǔ)

以上就是Javascript異步編程的詳細(xì)內(nèi)容,更多關(guān)于Javascript異步編程的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: JavaScript
相關(guān)文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
久久机这里只有精品| 日韩高清在线一区| 亚洲综合色视频| 国产在线精品二区| www激情久久| 国产精品一区免费在线观看| 欧美视频在线一区二区三区| 蜜臀av性久久久久蜜臀aⅴ | 欧美一级专区| 一区二区三区精品视频| 国产一级久久| 一区二区在线看| 亚洲视频播放| 一区二区三区**美女毛片| 亚洲久久成人| 综合中文字幕亚洲| 国内精品久久国产| 中文字幕不卡三区| 亚洲黄色一区| 亚洲欧美另类在线| 亚洲黄色影院| 亚洲一区二区欧美激情| 久久国产精品久久w女人spa| 亚洲国产美女搞黄色| 国产欧美日韩在线播放 | 亚洲欧洲日韩av| 99av国产精品欲麻豆| 亚洲日本在线看| 亚洲高清不卡| 亚洲精品国产无套在线观| 妖精视频成人观看www| 亚洲亚洲人成综合网络| 麻豆精品91| 开心九九激情九九欧美日韩精美视频电影 | 国产日本精品| 亚洲午夜精品17c| 美脚丝袜一区二区三区在线观看| 亚洲一区在线观看免费| 欧美亚洲网站| 婷婷中文字幕综合| 在线观看国产精品网站| 国产精品一区二区三区四区| 欧美一区二区视频在线观看2020 | 黄网站免费久久| 日韩欧美国产1| 99re在线精品| 国产精品美女久久久久久2018 | 欧美另类高清zo欧美| 成人爱爱电影网址| 国产精品久久久久久久久晋中| 99www免费人成精品| 奇米一区二区三区| 欧美一区二区三区性视频| 波波电影院一区二区三区| 国产精品色在线观看| 国产精品色网| 久久99九九99精品| 欧美mv日韩mv国产| 激情综合在线| 亚洲成av人片在线| 欧美亚洲综合一区| 高清日韩电视剧大全免费| 中文字幕av一区 二区| 亚洲一区二区伦理| 狠狠色丁香婷综合久久| 久久久久久久综合| 国产伦精品一区二区三区视频黑人 | 亚洲经典一区| 日韩精品电影一区亚洲| 日韩欧美国产综合在线一区二区三区| 99视频在线精品| 亚洲一区欧美一区| 91精品久久久久久久91蜜桃| 国产综合18久久久久久| 日韩成人一级大片| 欧美一级黄色片| 在线成人www免费观看视频| 开心九九激情九九欧美日韩精美视频电影 | 爽好久久久欧美精品| 日韩精品一区二区三区swag| 亚洲日本欧美| 狠狠色综合播放一区二区| 中文字幕欧美三区| 色猫猫国产区一区二在线视频| 国产盗摄一区二区三区| 最新国产の精品合集bt伙计| 91国偷自产一区二区开放时间| 成人av资源在线| 亚洲一区二区三区四区五区黄 | 日本在线不卡一区| 国产日韩在线不卡| 一本大道久久a久久精二百| 99热这里都是精品| 爽爽淫人综合网网站| 国产天堂亚洲国产碰碰| 色吊一区二区三区| 国产精品豆花视频| 久久99精品视频| 综合久久久久久| 欧美一二三四区在线| 99在线精品视频在线观看| 高清在线观看日韩| 三级欧美韩日大片在线看| 久久九九久精品国产免费直播| 久久xxxx精品视频| 91网站最新地址| 麻豆高清免费国产一区| 中文字幕制服丝袜成人av| 欧美色网一区二区| 亚洲日本激情| 成人在线视频首页| 婷婷开心激情综合| 国产三级精品三级在线专区| 欧美三级资源在线| 亚洲激情综合| 不卡的av在线播放| 久久成人麻豆午夜电影| 亚洲精品你懂的| 久久亚洲影视婷婷| 在线亚洲一区观看| 亚洲精品婷婷| 色综合久久综合网97色综合| 激情六月婷婷综合| 亚洲电影中文字幕在线观看| 国产欧美日韩视频一区二区| 欧美自拍偷拍一区| 亚洲激情一区| 99久久久无码国产精品| 奇米影视一区二区三区| 亚洲欧美一区二区久久| 久久久久国产精品人| 91精品啪在线观看国产60岁| 久久久xxx| 国产亚洲欧美一区二区| 欧美日韩大片一区二区三区| 成人性视频网站| 国产综合色在线视频区| 日韩精品欧美精品| 一区二区三区在线观看动漫| 国产日韩欧美精品电影三级在线| 欧美丰满少妇xxxxx高潮对白 | 欧美国产一区视频在线观看| 91精品福利在线一区二区三区| 在线观看日韩av先锋影音电影院| 国产日产高清欧美一区二区三区| 欧美精品一级| 99久久99久久免费精品蜜臀| 激情五月激情综合网| 午夜精品福利在线| 亚洲精品日韩一| 亚洲图片你懂的| 国产欧美日韩中文久久| 久久综合99re88久久爱| 欧美一区二区三区免费大片 | 欧美精品aⅴ在线视频| 久久精品综合| 欧美亚洲一级| 午夜在线观看免费一区| 日韩视频在线播放| 亚洲国产精品一区在线观看不卡| 91丝袜呻吟高潮美腿白嫩在线观看| 国产剧情av麻豆香蕉精品| 久久国产尿小便嘘嘘| 美女视频黄a大片欧美| 免费人成黄页网站在线一区二区| 亚洲成人福利片| 亚洲一区二区三区四区在线观看| 伊人开心综合网| 亚洲天堂免费看| 中文字幕日韩一区| 国产精品第四页| 亚洲欧洲精品成人久久奇米网| 国产片一区二区三区| 欧美极品xxx| 中文字幕精品三区| 国产精品色哟哟网站| 国产精品午夜久久| 国产精品免费看片| 18成人在线观看| 亚洲欧美国产高清| 一区二区欧美国产| 亚洲午夜免费电影| 亚洲成av人影院| 日韩中文字幕av电影| 人人精品人人爱| 九九在线精品视频| 国产另类ts人妖一区二区| 成人午夜在线视频| 99麻豆久久久国产精品免费 | 色琪琪一区二区三区亚洲区| 久久三级福利| 欧美午夜精品一区二区三区| 欧美日韩久久久| 欧美一区二区视频免费观看| 久久综合狠狠综合久久综合88 | 亚洲国产日韩欧美| 国产精品最新自拍| 在线观看亚洲成人| 欧美日韩视频在线第一区| 91精品国产色综合久久ai换脸|