亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 開發 > JS > 正文

JS異步處理的進化史深入講解

2024-05-06 16:54:32
字體:
來源:轉載
供稿:網友

前言

javascript是一門單線程的語言,也就是說一次只能完成一件任務,如果有多個任務,就需要排隊進行處理。如果一個任務耗時很長,后面的任務也必須排隊等待,這樣大大的影響了整個程序的執行。為了解決這個問題,javascript語言將任務分為兩種模式:

  • 同步:當我們打開網站,網頁的頁面骨架渲染和頁面元素渲染,就是一大推同步任務。
  • 異步:我們在瀏覽新聞時,加載圖片或音樂之類占用資源大且耗時久的任務就是異步任務。

本文主要針對近兩年javascript的發展,主要介紹異步處理的進化史。目前,在javascript異步處理中,有以下幾種方式:

JS,異步處理

callback

回調函數是最早解決異步編程的方法。無論是常見的setTimeout還是ajax請求,都是采用回調的形式把事情在某一固定的時刻進行執行。

 //常見的:setTimeout setTimeout(function callback(){  console.log('aa'); }, 1000); //ajax請求 ajax(url,function callback(){  console.log("ajax success",res); })

回調函數的處理一般將函數callback作為參數傳進函數,在合適的時候被調用執行?;卣{函數的優點就是簡單、容易理解和實現,但有個致命的缺點,容易出現回調地獄(Callback hell),即多個回調函數嵌套使用。造成代碼可讀性差、可維護性差且只能在回調中處理異常。

ajax(url, () => {	//todo	ajax(url1, () => {		//todo		ajax(url2, () => {			//todo		})	})})

事件監聽

事件監聽采用的是事件驅動的模式。事件的執行不取決于代碼的順序,而是某個事件的發生。

假設有兩個函數,為f1綁定一個事件(jQuery的寫法),當f1函數發生success事件時,執行函數f2:

f1.on('success',f2);

對f1進行改寫:

function f1(){	ajax(url,() => {		//todo		f1.trigger('success');//觸發success事件,從而執行f2函數	})}

事件監聽的方式較容易理解,可以綁定多個事件,每個事件可以指定多個回調函數,而且可以"去耦合",有利于實現模塊化。缺點是整個程序都要變成事件驅動型,運行流程會變得很不清晰。閱讀代碼的時候,很難看出主流程。

發布訂閱

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

//利用jquery的插件實現//首先,f2向消息中心訂閱success事件jQuery.subscribe('success',f2);//對f1進行改寫:function f1(){	ajax(url,() => {		//todo		jQuery.publish('success');//當f1執行完畢后,向消息中心jQuery發布success事件,從而執行f2函數	})}//f2執行完畢后,可以取消訂閱jQuery.unsubscribe('success',f2)

該方法和事件監聽的性質類似,但我們可以通過消息中心來查閱一共有多少個信號,每個信號有多少個訂閱者。

Promise

**Promise**是CommonJS工作組提出的一種規范,可以獲取異步操作的消息,也是異步處理中常用的一種解決方案。Promise的出現主要是用來解決回調地獄、支持多個并發的請求,獲取并發請求的數據并且解決異步的問題。

let p = new Promise((resolve, reject) => { //做一些異步操作 setTimeout(()=>{  let num = parseInt(Math.random()*100);  	if(num > 50){   resolve("num > 50"); // 如果數字大于50就調用成功的函數,并且將狀態變成Resolved  	}else{   	reject("num <50");// 否則就調用失敗的函數,將狀態變成Rejected  }	},10000)});p.then((res) => {	console.log(res);}).catch((err) =>{ console.log(err);})

Promise有三種狀態:等待pending、成功fulfied、失敗rejected;狀態一旦改變,就不會再變化,在Promise對象創建后,會馬上執行。等待狀態可以變為fulfied狀態并傳遞一個值給相應的狀態處理方法,也可能變為失敗狀態rejected并傳遞失敗信息。任一一種情況出現時,Promise對象的 then 方法就會被調用(then方法包含兩個參數:onfulfilled 和 onrejected,均為 Function。當Promise狀態為fulfilled時,調用 then 的 onfulfilled 方法,當Promise狀態為rejected時,調用 then 的 onrejected 方法)。

需要注意的是: Promise.prototype.then 和  Promise.prototype.catch 方法返回promise 對象, 所以可以被鏈式調用,如下圖:

JS,異步處理

Promise的方法:

  • Promise.all(iterable):誰執行得慢,以誰為準執行回調。返回一個promise對象,只有當iterable里面的所有promise對象成功后才會執行。一旦iterable里面有promise對象執行失敗就觸發該對象的失敗。對象在觸發成功后,會把一個包iterable里所有promise返回值的數組作為成功回調的返回值,順序跟iterable的順序保持一致;如果這個新的promise對象觸發了失敗狀態,它會把iterable里第一個觸發失敗的promise對象的錯誤信息作為它的失敗錯誤信息。Promise.all方法常被用于處理多個promise對象的狀態集合。
  • Promise.race(iterable): 誰執行得快,以誰為準執行回調。iterable參數里的任意一個子promise被成功或失敗后,父promise馬上也會用子promise的成功返回值或失敗詳情作為參數調用父promise綁定的相應句柄,并返回該promise對象。
  • Promise.reject(err)與Promise.resolve(res)

Generators/yield

Generators是ES6提供的異步解決方案,其最大的特點就是可以控制函數的執行??梢岳斫獬梢粋€內部封裝了很多狀態的狀態機,也是一個遍歷器對象生成函數。Generator 函數的特征:

  • function關鍵字與函數名之間有一個星號;
  • 函數體內部使用yield表達式,定義不同的內部狀態;
    • 通過yield暫停函數,next啟動函數,每次返回的是yield表達式結果。next可以接受參數,從而實現在函數運行的不同階段,可以從外部向內部注入不同的值。next返回一個包含value和done的對象,其中value表示迭代的值,后者表示迭代是否完成。

舉個例子:

function* createIterator(x) { let y = yield (x+1) let z = 2*(yield(y/3)) return (x+y+z)}// generators可以像正常函數一樣被調用,不同的是會返回一個 iteratorlet iterator = createIterator(4);console.log(iterator.next()); // {value:5,done:false}console.log(iterator.next()); // {value:NaN,done:false}console.log(iterator.next()); // {value:NaN,done:true}let iterator1 = createIterator(4);//返回一個iterator//next傳參數console.log(iterator1.next());  // {value:5,done:false}console.log(iterator1.next(12)); // {value:4,done:false}console.log(iterator1.next(15)); // {value:46,done:true}

代碼分析:

  • 當不參數時,next的value返回NaN;
  • 當傳參數時,作為上一個yeild的值,在第一次使用next時,傳參數無效,只有第二次開始,才有效。
  • 第一次執行next時,函數會被暫停在yeild(x+1),所以返回的是4+1=5;
  • 第二次執行next時,傳入的12為上一次yeild表達式的值,所以y=12,返回的是12/3=4;
  • 第三次執行next時,傳入的15為上一次yeild表達式的值,所以z=30,y=12;x=4,返回30+12+4=46

async/await

初入async/await

async/await在ES7提出,是目前在javascript異步處理的終極解決方案。

async 其本質是 Generator 函數的語法糖。相較于Generator放入改進如下:

  • 內置執行器:Generator 函數的執行必須靠執行器,而async函數自帶執行器。其調用方式與普通函數一模一樣,不需要調next方法;
  • 更好的語義:async表示定義異步函數,而await表示后面的表達式需要等待,相較于*和yeild更語義化;
  • 更廣的適用性:co模塊約定,yield命令后面只能是Thunk函數或 Promise對象。而 async 函數的await命令后面則可以是Promise 或者 原始類型的值;
  • 返回Promise:async 函數返回值是Promise對象,比 Generator函數返回的 Iterator對象方便,可以直接使用 then() 方法進行鏈式調用;

語法分析

async語法

用來定義異步函數,自動將函數轉換為promise對象,可以使用then來添加回調,其內部return的值作為then回調的參數。

async function f(){	return "hello async";}f().then((res) => {  //通過then來添加回調且內部返回的res作為回調的參數	console.log(res);  // hello async})

在異步函數的內部可以使用await,其返回的promise對象必須等到內部所以await命令后的promise對象執行完,才會發生狀態變化即執行then回調。

const delay = function(timeout){ 	return new Promise(function(resolve){		return setTimeout(resolve, timeout); });}async function f(){  await delay(1000);  await delay(2000);  return '完成';}f().then(res => console.log(res));//需要等待3秒之后才會打?。和瓿?/pre>

await即表示異步等待,用來暫停異步函數的執行,只能在異步函數和promise使用,且當使用在promise前面,表示等待promise完成并返回結果。

async function f() {  return await 1  //await后面不是Promise的話,也會被轉換為一個立即為resolve的promise};f().then( res => console.log("處理成功",res))//打印出:處理成功 1	 .catch(err => console.log("處理是被",err))////打印出:Promise{<resolved>:undefined}

錯誤處理

如果await后面的異步出現錯誤,等同于async返回的promise對象為reject,其錯誤會被catch的回調函數接收到。需要注意的是,當 async 函數中只要一個 await 出現 reject 狀態,則后面的 await 都不會被執行。

let a;async function f(){  await Promise.reject("error")  a = await 1    //該await并沒有執行 }err().then(res => console.log(a))

怎么處理呢,可以把第一個await放在try/catch,遇到函數的時候,可以將錯誤拋出并往下執行。

async function f() {   try{     await Promise.reject('error');    }catch(error){    console.log(error);  }  return await 1}f().then(res => console.log('成功', res))//成功打印出1

如果有多個await處理,可以統一放在try/catch模塊中,而且async可以使得try/catch同時處理同步和異步錯誤。

總結

通過以上六種javascript異步處理的常用方法,可以看出async/await可以說是異步終極解決方案了,最后看一下async/await用得最多的場景:

如果一個業務需要很多個異步操作組成,并且每個步驟都依賴于上一步的執行結果,這里采用不同的延時來體現:

//首先定義一個延時函數function delay(time) {  return new Promise(resolve => {    setTimeout(() => resolve(time), time);  });}//采用promise鏈式調用實現delay(500).then(result => {  return delay(result + 1000)}).then(result => {  return delay(result + 2000)}).then(result => {  console.log(result)  //3500ms后打印出3500}).catch(error => {  console.log(error)}) //采用async實現async function f(){ const r1 = await delay(500) const r2 = await delay(r1+1000) const r3 = await delay(r2+2000) return r3}f().then(res =>{ console.log(res)}).catch(err=>{ console.log(err)})

可以看出,采用promise實現采用了很多then進行不停的鏈式調用,使得代碼變得冗長和復雜且沒有語義化。而 async/await首先使用同步的方法來寫異步,代碼非常清晰直觀,而且使代碼語義化,一眼就能看出代碼執行的順序,最后 async 函數自帶執行器,執行的時候無需手動加載。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對VeVb武林網的支持。


注:相關教程知識閱讀請移步到JavaScript/Ajax教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
宅男66日本亚洲欧美视频| 久久国产精品久久久| 欧美日韩在线第一页| 国产美女精品视频免费观看| 国产成人福利视频| 国产精品高潮呻吟久久av野狼| 在线免费观看羞羞视频一区二区| 在线视频国产日韩| 日韩69视频在线观看| 欧美日韩高清区| 欧美在线视频一区二区| 国产精品女视频| 欧美亚洲国产日韩2020| 国产精品久久久久久网站| 日本免费在线精品| 韩曰欧美视频免费观看| 日韩免费观看在线观看| 性欧美办公室18xxxxhd| 欧美中文字幕在线视频| 久久在线视频在线| 国产精品久久一| 欧美日韩性视频| 亚洲色图色老头| 国产精品视频精品视频| 成人欧美一区二区三区在线湿哒哒| 久久久久久伊人| 国产拍精品一二三| 国产丝袜一区二区| 日韩av网站在线| www.亚洲成人| 夜夜嗨av色综合久久久综合网| 亚洲成人三级在线| 国产精品入口免费视频一| 欧美日韩国产专区| 97精品国产97久久久久久| 久久久久日韩精品久久久男男| 福利微拍一区二区| 欧美另类极品videosbestfree| 久久视频在线免费观看| 精品一区电影国产| 91国内揄拍国内精品对白| 亚洲深夜福利视频| 久久久久久久久中文字幕| 日韩av影院在线观看| 2019中文字幕免费视频| 色婷婷亚洲mv天堂mv在影片| 欧美极品第一页| 日韩精品在线视频观看| 91九色视频导航| 亚洲国产一区二区三区四区| 亚洲国产精品久久精品怡红院| 国产精品高清免费在线观看| 亚洲人成伊人成综合网久久久| 久久久精品在线| 97视频在线免费观看| 亚洲国产精品电影| 九九视频这里只有精品| 亚洲欧美日韩国产中文| 欧美日韩在线视频观看| 亚洲国产97在线精品一区| 国产成人在线一区| 亚洲国产精品久久| 欧美国产日韩一区二区在线观看| 亚洲天堂男人的天堂| 国产精品美女主播在线观看纯欲| 国产精品www| 国产欧美一区二区三区四区| 2019中文字幕免费视频| 亚洲爱爱爱爱爱| 中文字幕亚洲欧美日韩2019| 美女黄色丝袜一区| 91精品国产免费久久久久久| 欧美视频在线观看免费网址| 一本大道久久加勒比香蕉| 欧美电影院免费观看| 欧美一级电影免费在线观看| 欧美激情精品久久久久久| 高清欧美电影在线| 激情久久av一区av二区av三区| 福利视频导航一区| 亚洲福利视频网| 国产精品自拍网| 亚洲最大福利视频网站| 亚洲精品一区二区网址| 欧美高清videos高潮hd| 久热在线中文字幕色999舞| 亚洲娇小xxxx欧美娇小| 精品少妇一区二区30p| 97视频免费在线观看| 欧美激情精品在线| 精品偷拍各种wc美女嘘嘘| 国产精品久久久久久久久久ktv| 国产午夜精品一区二区三区| 亚洲国产欧美久久| 欧洲亚洲女同hd| 日韩av网址在线观看| 欧美一区亚洲一区| 久久综合免费视频影院| 国产精品免费视频xxxx| 亚洲精品美女免费| 久久综合伊人77777| 欧美成人一区在线| 亚洲在线一区二区| 欧美激情精品久久久久久大尺度| 欧美性视频在线| 国内精品久久久| 91免费人成网站在线观看18| 欧美激情18p| 人人做人人澡人人爽欧美| 日韩在线视频中文字幕| 久久精品99久久久香蕉| 亚洲精品狠狠操| 亚洲国产成人精品久久久国产成人一区| 97在线视频免费看| 日本一欧美一欧美一亚洲视频| 国产一区二区三区欧美| 亚洲国产精品人久久电影| 久久97久久97精品免视看| 日韩欧美在线观看| 欧美夜福利tv在线| 国产亚洲精品成人av久久ww| 亚洲黄色www网站| 欧美裸体xxxx| 亚洲第一视频网| 欧美激情精品久久久| 草民午夜欧美限制a级福利片| 亚洲日本中文字幕| 亚洲精品成人网| 国产97在线|日韩| 日韩在线免费高清视频| 亚洲性夜色噜噜噜7777| 自拍偷拍亚洲精品| 8090理伦午夜在线电影| 日韩精品在线视频观看| 97精品久久久| 一区二区三区 在线观看视| 久久激情视频久久| 欧美精品www| 亚洲精品动漫久久久久| 国产亚洲精品久久久久久| 日韩小视频在线| 日韩福利视频在线观看| 日韩性xxxx爱| 国产中文字幕亚洲| 日韩欧美一区二区在线| 久久久精品在线观看| 91网站在线看| 精品无人区乱码1区2区3区在线| 精品免费在线视频| 亚洲自拍偷拍福利| 日韩免费在线看| 久久亚洲影音av资源网| 在线视频日韩精品| 国产男女猛烈无遮挡91| 欧美午夜视频在线观看| 亚洲成年人影院在线| 国产成人jvid在线播放| 黄网动漫久久久| 国产精品久久久久久久av大片| 日韩美女视频免费看| 亲爱的老师9免费观看全集电视剧| 日本成熟性欧美| 91精品视频专区| 日韩中文字幕国产|