偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

總結(jié)JavaScript處理異步的方法

開發(fā) 前端
javascript語言的執(zhí)行環(huán)境是單線程(single thread),就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執(zhí)行后面一個任務,以此類推。

javascript語言的執(zhí)行環(huán)境是單線程(single thread),就是指一次只能完成一件任務。如果有多個任務,就必須排隊,前面一個任務完成,再執(zhí)行后面一個任務,以此類推。

[[321194]]

這種模式的好處是實現(xiàn)起來比較簡單,執(zhí)行環(huán)境相對單純;但是只要耗時比較多,假如有一個任務耗時很長,后面的任務都必須排隊等著,會拖延整個程序的執(zhí)行。為了解決這個問題,Javascript語言將任務的執(zhí)行模式分成兩種:同步(Synchronous)和異步(Asynchronous)。

  • 同步模式:就是一個任務先執(zhí)行,后一個任務等待前一個任務結(jié)束,然后再執(zhí)行,程序的執(zhí)行順序與任務的排列順序是一致的、同步的;
  • 異步模式::每一個任務有一個或多個回調(diào)函數(shù)(callback),前一個任務結(jié)束后,不是執(zhí)行后一個任務,而是執(zhí)行回調(diào)函數(shù),后一個任務則是不等前一個任務結(jié)束就執(zhí)行,所以程序的執(zhí)行順序與任務的排列順序是不一致的、異步的。

Javascript處理異步的方法有以下幾種:

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

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

  1. ajax('XXX1', () => { 
  2.   // callback 函數(shù)體 
  3.   ajax('XXX2', () => { 
  4.     // callback 函數(shù)體 
  5.     ajax('XXX3', () => { 
  6.       // callback 函數(shù)體 
  7.     }) 
  8.   }) 
  9. }) 

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

  • 代碼臃腫,可讀性差,可維護性差。
  • 代碼復用性差。
  • 容易滋生 bug。
  • 只能在回調(diào)里處理異常。

二、事件監(jiān)聽

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

(1) 普通方式

  1. f1.on('done', f2); 

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

(2) onclick方法

  1. element.onclick=function(){ 
  2.    //處理函數(shù) 
  3.  
  4. element.onclick=handler1
  5. element.onclick=handler2
  6. element.onclick=handler3
  7. // 只有handler3會被添加執(zhí)行 

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

缺點:當同一個element元素綁定多個事件時,只有最后一個事件會被添加

(3) addEvenListener

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

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

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

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

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

  1. jQuery.subscribe('done', f2); 

然后,f1進行如下改寫:

  1. function f1() { 
  2.   setTimeout(function () { 
  3.     jQuery.publish('done'); 
  4.   }, 1000); 

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

  1. jQuery.unsubscribe('done', f2); 

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

四、promise

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

Promise 對象有以下兩個特點。

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

1. 基本用法

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

  1. const promise = new Promise((resolve, reject) => { 
  2.   if (/* 異步操作成功 */){ 
  3.     resolve(success) 
  4.   } else { 
  5.     reject(error) 
  6.   } 
  7. }) 

Promise接收一個函數(shù)作為參數(shù),函數(shù)里有resolve和reject兩個參數(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ù)傳遞出去。
  • 他們之間只能有一個被執(zhí)行,不會同時被執(zhí)行,因為Promise只能保持一種狀態(tài)。

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

  1. promise.then((success) => { 
  2.   // 對應于上面的resolve(success)方法 
  3. }, (error) => { 
  4.   // 對應于上面的reject(error)方法 
  5.  
  6.  
  7. // 還可以寫成這樣 (推薦使用這種寫法) 
  8. promise.then((success) => { 
  9.   // 對應于上面的resolve(success)方法 
  10. }).catch((error) => { 
  11.   // 對應于上面的reject(error)方法 
  12. }) 

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

  • 第一個參數(shù)執(zhí)行的是resolve()方法(即異步成功后的回調(diào)方法)
  • 第二參數(shù)執(zhí)行的是reject()方法(即異步失敗后的回調(diào)方法)(第二個參數(shù)可選)。
  • 它返回的是一個新的Promise對象。

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

  1. const promise = new Promise((resolve, reject) => { 
  2.   console.log(1) 
  3.   resolve() 
  4.   console.log(2) 
  5. }) 
  6.  
  7. promise.then(() => { 
  8.   console.log(3) 
  9. }) 
  10.  
  11. console.log(4) 
  12. // 1  2  4   3 

2. Promise.finally()

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

  1. promise 
  2. .then(result => {···}) 
  3. .catch(error => {···}) 
  4. .finally(() => {···}); 

3. Promise.all()

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

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

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

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

4. Promse.race()

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

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

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

五、async/await

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

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

  • 內(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,但這時等同于同步)。
  • 返回值是 Promise。async 函數(shù)返回值是 Promise 對象,比 Generator 函數(shù)返回的 Iterator 對象方便,可以直接使用 then() 方法進行調(diào)用。

1. 使用規(guī)則

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

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

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

  1. function test() { 
  2.   let result = await Promise.resolve('success') 
  3.   console.log(result) 
  4.  
  5. test()   //執(zhí)行以后會報錯 

2. await 在等什么

  • 如果await等到的不是一個promise對象,那跟著的表達式的運算結(jié)果就是它等到的東西;
  • 如果是一個promise對象,await會阻塞后面的代碼,等promise對象resolve,得到resolve的值作為await表達式的運算結(jié)果
  • 雖然await阻塞了,但await在async中,async不會阻塞,它內(nèi)部所有的阻塞都被封裝在一個promise對象中異步執(zhí)行 

 

責任編輯:趙寧寧 來源: 前端先鋒隊
相關推薦

2017-08-28 15:21:29

異步處理回調(diào)函數(shù)異步編程

2023-11-29 07:38:33

JavaScript異步處理

2009-02-17 11:23:08

2013-01-07 10:44:00

JavaScriptjQueryJS

2010-03-09 17:04:37

2010-03-09 16:53:58

2010-12-01 14:34:59

AsyncTask異步處理任務Android

2010-02-24 09:59:19

WCF服務異步代理

2020-12-21 16:35:51

JavaScript網(wǎng)頁截屏代碼

2020-10-15 13:29:57

javascript

2011-04-08 09:16:12

JavaScript

2023-05-09 15:01:43

JavaScript編程語言異常處理

2022-12-01 08:30:10

JavaScript構(gòu)造函數(shù)

2021-12-10 07:47:30

Javascript異步編程

2018-11-08 15:30:04

JavaScriptES6異步

2017-07-06 17:39:53

JavaScript開發(fā)程序員

2023-03-16 15:13:41

缺失值據(jù)集中數(shù)據(jù)分析

2009-09-01 18:16:41

C#窗體間通訊

2016-09-07 20:43:36

Javascript異步編程

2017-07-13 12:12:19

前端JavaScript異步編程
點贊
收藏

51CTO技術棧公眾號