JavaScript中怎么處理異步

JavaScript中怎么處理異步,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個(gè)問題。

10余年的余干網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。網(wǎng)絡(luò)營銷推廣的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整余干建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。成都創(chuàng)新互聯(lián)公司從事“余干網(wǎng)站設(shè)計(jì)”,“余干網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

一、回調(diào)函數(shù)

回調(diào)是一個(gè)函數(shù)被作為一個(gè)參數(shù)傳遞到另一個(gè)函數(shù)里,在那個(gè)函數(shù)執(zhí)行完后再執(zhí)行?;卣{(diào)函數(shù)是異步編程最基本的方法,其優(yōu)點(diǎn)是簡單、容易理解和部署;缺點(diǎn)是容易產(chǎn)生回調(diào)地獄。

ajax('XXX1', () => {   // callback 函數(shù)體   ajax('XXX2', () => {     // callback 函數(shù)體     ajax('XXX3', () => {       // callback 函數(shù)體     })   }) })

這就是所謂的回調(diào)地獄,回調(diào)地獄帶來的負(fù)面作用有以下幾點(diǎn):

  • 代碼臃腫,可讀性差,可維護(hù)性差。

  • 代碼復(fù)用性差。

  • 容易滋生 bug。

  • 只能在回調(diào)里處理異常。

二、事件監(jiān)聽

這種方式,異步任務(wù)的執(zhí)行不取決于代碼的順序,而取決于某個(gè)事件是否發(fā)生。

(1) 普通方式

f1.on('done', f2);

上面這行代碼的意思是,當(dāng)f1發(fā)生done事件,就執(zhí)行f2。

(2) onclick方法

element.onclick=function(){    //處理函數(shù) }  element.onclick=handler1; element.onclick=handler2; element.onclick=handler3; // 只有handler3會被添加執(zhí)行

優(yōu)點(diǎn):寫法兼容到主流瀏覽器;

缺點(diǎn):當(dāng)同一個(gè)element元素綁定多個(gè)事件時(shí),只有最后一個(gè)事件會被添加

(3) addEvenListener

elment.addEvenListener("click",handler1,false); elment.addEvenListener("click",handler2,false); elment.addEvenListener("click",handler3,false);

該方法的第三個(gè)參數(shù)是一個(gè)布爾值:當(dāng)為false時(shí)表示由里向外,true表示由外向里。

三、發(fā)布/訂閱模式

我們假定,存在一個(gè)"信號中心",某個(gè)任務(wù)執(zhí)行完成,就向信號中心"發(fā)布"(publish)一個(gè)信號,其他任務(wù)可以向信號中心"訂閱"(subscribe)這個(gè)信號,從而知道什么時(shí)候自己可以開始執(zhí)行。這就叫做"發(fā)布/訂閱模式"(publish-subscribe  pattern)

首先,f2向信號中心jQuery訂閱done信號。

jQuery.subscribe('done', f2);

然后,f1進(jìn)行如下改寫:

function f1() {   setTimeout(function () {     jQuery.publish('done');   }, 1000); }

f1執(zhí)行完成后,向信號中心jQuery發(fā)布done信號,從而引發(fā)f2的執(zhí)行。f2完成執(zhí)行后,可以取消訂閱(unsubscribe)

jQuery.unsubscribe('done', f2);

這種方式的優(yōu)點(diǎn):可以通過查看“消息中心”,了解存在多少信號、每個(gè)信號有多少訂閱者,從而監(jiān)控程序的運(yùn)行。

四、promise

以上都是ES6之前的異步處理方式。ES6之后出現(xiàn)了promise。它是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù))——更合理和更強(qiáng)大。

Promise 對象有以下兩個(gè)特點(diǎn)。

  • 對象的狀態(tài)不受外界影響。Promise  對象代表一個(gè)異步操作,有三種狀態(tài):pending(進(jìn)行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個(gè)狀態(tài)。

  • 一旦狀態(tài)改變,就不會再變,任何時(shí)候都可以得到這個(gè)結(jié)果

1. 基本用法

(1) ES6 規(guī)定,Promise 對象是一個(gè)構(gòu)造函數(shù),用來生成 Promise 實(shí)例。

const promise = new Promise((resolve, reject) => {   if (/* 異步操作成功 */){     resolve(success)   } else {     reject(error)   } })

Promise接收一個(gè)函數(shù)作為參數(shù),函數(shù)里有resolve和reject兩個(gè)參數(shù):

  • resolve方法的作用是將Promise的pending狀態(tài)變?yōu)閒ullfilled,在異步操作成功之后調(diào)用,可以將異步返回的結(jié)果作為參數(shù)傳遞出去。

  • reject方法的作用是將Promise的pending狀態(tài)變?yōu)閞ejected,在異步操作失敗之后調(diào)用,可以將異步返回的結(jié)果作為參數(shù)傳遞出去。

  • 他們之間只能有一個(gè)被執(zhí)行,不會同時(shí)被執(zhí)行,因?yàn)镻romise只能保持一種狀態(tài)。

(2) Promise 實(shí)例生成以后,可以用then方法分別指定resolved狀態(tài)和rejected狀態(tài)的回調(diào)函數(shù)。

promise.then((success) => {   // 對應(yīng)于上面的resolve(success)方法 }, (error) => {   // 對應(yīng)于上面的reject(error)方法 }   // 還可以寫成這樣 (推薦使用這種寫法) promise.then((success) => {   // 對應(yīng)于上面的resolve(success)方法 }).catch((error) => {   // 對應(yīng)于上面的reject(error)方法 })

then(onfulfilled,onrejected)方法中有兩個(gè)參數(shù),兩個(gè)參數(shù)都是函數(shù):

  • 第一個(gè)參數(shù)執(zhí)行的是resolve()方法(即異步成功后的回調(diào)方法)

  • 第二參數(shù)執(zhí)行的是reject()方法(即異步失敗后的回調(diào)方法)(第二個(gè)參數(shù)可選)。

  • 它返回的是一個(gè)新的Promise對象。

(3) promise構(gòu)造函數(shù)是同步執(zhí)行的,then方法是異步執(zhí)行的

const promise = new Promise((resolve, reject) => {   console.log(1)   resolve()   console.log(2) })  promise.then(() => {   console.log(3) })  console.log(4) // 1  2  4   3

2. Promise.finally()

Promise.finally()用于指定不管 Promise 對象最后狀態(tài)如何,都會執(zhí)行的操作。

promise .then(result => {···}) .catch(error => {···}) .finally(() => {···});

3. Promise.all()

Promise.all()用于處理多個(gè)異步處理,比如說一個(gè)頁面上需要等多個(gè) ajax 的數(shù)據(jù)回來才執(zhí)行相關(guān)邏輯。

const p = Promise.all([p1, p2, p3]);

p的狀態(tài)由p1、p2、p3決定,分成兩種情況。

  • 只有p1、p2、p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled,此時(shí)p1、p2、p3的返回值組成一個(gè)數(shù)組,傳遞給p的回調(diào)函數(shù)。

  • 只要p1、p2、p3之中有一個(gè)被rejected,p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會傳遞給p的回調(diào)函數(shù)。

4. Promse.race()

Promse.race()就是賽跑的意思,Promise.race([p1, p2,  p3])里面哪個(gè)結(jié)果獲得的快,就返回那個(gè)結(jié)果,不管結(jié)果本身是成功狀態(tài)還是失敗狀態(tài)。

const p = Promise.race([p1, p2, p3])

上面代碼中,只要p1、p2、p3之中有一個(gè)實(shí)例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個(gè)率先改變的 Promise  實(shí)例的返回值,就傳遞給p的回調(diào)函數(shù)。

五、async/await

async/await是JavaScript為了解決異步問題而提出的一種解決方案,許多人將其稱為異步的終極解決方案。async 函數(shù),就是  Generator 函數(shù)的語法糖。

相較于 Generator,Async 函數(shù)的改進(jìn)在于下面四點(diǎn):

  • 內(nèi)置執(zhí)行器。Generator 函數(shù)的執(zhí)行必須依靠執(zhí)行器,而 Aysnc 函數(shù)自帶執(zhí)行器,調(diào)用方式跟普通函數(shù)的調(diào)用一樣。

  • 更好的語義。async 和 await 相較于 * 和 yield 更加語義化。

  • 更廣的適用性。co 模塊約定,yield 命令后面只能是 Thunk 函數(shù)或 Promise對象。而 async 函數(shù)的 await 命令后面可以是  Promise 或者原始類型(Number,string,boolean,但這時(shí)等同于同步)。

  • 返回值是 Promise。async 函數(shù)返回值是 Promise 對象,比 Generator 函數(shù)返回的 Iterator 對象方便,可以直接使用  then() 方法進(jìn)行調(diào)用。

1. 使用規(guī)則

(1) 凡是在前面添加了async的函數(shù)在執(zhí)行后都會自動返回一個(gè)Promise對象

async function test() {      }  let result = test() console.log(result)  //即便代碼里test函數(shù)什么都沒返回,我們依然打出了Promise對象

(2) await必須在async函數(shù)里使用,不能單獨(dú)使用

function test() {   let result = await Promise.resolve('success')   console.log(result) }  test()   //執(zhí)行以后會報(bào)錯(cuò)

2. await 在等什么

  • 如果await等到的不是一個(gè)promise對象,那跟著的表達(dá)式的運(yùn)算結(jié)果就是它等到的東西;

  • 如果是一個(gè)promise對象,await會阻塞后面的代碼,等promise對象resolve,得到resolve的值作為await表達(dá)式的運(yùn)算結(jié)果

  • 雖然await阻塞了,但await在async中,async不會阻塞,它內(nèi)部所有的阻塞都被封裝在一個(gè)promise對象中異步執(zhí)行 

看完上述內(nèi)容,你們掌握J(rèn)avaScript中怎么處理異步的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

分享題目:JavaScript中怎么處理異步
標(biāo)題來源:http://muchs.cn/article32/pdjjsc.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供動態(tài)網(wǎng)站、定制網(wǎng)站微信公眾號、云服務(wù)器網(wǎng)站制作、自適應(yīng)網(wǎng)站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

成都定制網(wǎng)站網(wǎng)頁設(shè)計(jì)