js異步處理方案之異步串行與異步并行
js異步處理方案,js的異步串行與異步并行
一、什么是串行,并行,并發(fā)
串行:這個(gè)就像隊(duì)列一樣,一個(gè)執(zhí)行完,下一個(gè)再執(zhí)行,比如js同步執(zhí)行
并發(fā):是指這個(gè)系統(tǒng)擁有處理多個(gè)任務(wù)的能力,在一定時(shí)間發(fā)出,不需要同時(shí)性執(zhí)行。js的異步消息隊(duì)列讓js擁有并發(fā)的能力
? 比如執(zhí)行多個(gè)settimeout 它會(huì)掛載在消息隊(duì)列,然后依次執(zhí)行
并行:是指這個(gè)系統(tǒng)擁同時(shí)處理多個(gè)任務(wù)的能力,屬于多線(xiàn)程的一種方式,而js是屬于單線(xiàn)程 雖然可以通過(guò)worker來(lái)創(chuàng)建多線(xiàn)程,但是子線(xiàn)程
? 完全受主線(xiàn)程控制,沒(méi)有改變JavaScript單線(xiàn)程的本質(zhì)
串行示意圖:
有人會(huì)問(wèn),異步不是都在消息隊(duì)列嗎,不就是一個(gè)一個(gè)執(zhí)行了嗎?
舉個(gè)例子,如果本身就是串行執(zhí)行,那么你現(xiàn)在執(zhí)行2給個(gè)任務(wù),一個(gè)是5秒后打印console.log(1),一個(gè)是十秒后打印console.log(2)
按照串行應(yīng)該是15秒執(zhí)行完畢,但實(shí)際耗時(shí)是10秒,如上這是并發(fā),
console.time() setTimeout(() => { console.log(1) }, 5000); setTimeout(() => { console.log(2) console.timeEnd() }, 10000);
二、實(shí)現(xiàn)異步串行
大多時(shí)候我們可以用 promise 和async await來(lái)解決
promise
比較少的時(shí)候,可以用.then來(lái)實(shí)現(xiàn)串行
var a = function() { return new Promise((resolve, reject) => { setTimeout(() => { consloe.log('a') resolve('a') }, 3000) }) } var b = function() { return new Promise((resolve, reject) => { setTimeout(() => { consloe.log('b') resolve('b') }, 2000) }) }; console.time('test') a().then((aa) => { b().then((bb) => { console.log(`${aa}-${bb}`) console.timeEnd('test') }) })
async await
我們改造一下,明顯使用await看起來(lái)更加清晰
var a = function() { return new Promise((resolve, reject) => { setTimeout(() => { consloe.log('a') resolve('a') }, 3000) }) } var b = function() { return new Promise((resolve, reject) => { setTimeout(() => { consloe.log('b') resolve('b') }, 2000) }) }; (async () => { console.time('test') var aa = await a() var bb = await b() console.log(`${aa}-${bb}`) console.timeEnd('test') })()
但當(dāng)我們有多個(gè)異步,比如2000個(gè)該如何
var createPromise = function(time) { // then中的回調(diào)函數(shù) return (resolve, reject) => { return new Promise((resolve, reject) => { setTimeout(() => { //模擬請(qǐng)求 (真實(shí)使用把time設(shè)置為0,將resolve傳入異步函數(shù)中) console.log('timein' + time) resolve(); //在異步處理結(jié)束后resolve }, time * 1000) }) } } var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)]; function serpromise(arr) { arr.reduce((pre, next, index, carr) => { return pre.then(next) }, Promise.resolve()) } // 相當(dāng)于 // Promise.resolve().then(createPromise(2)).then(createPromise(1))...... serpromise(arr)
async await
var createPromise = function(time) { return () => { return new Promise((resolve, reject) => { setTimeout(() => { //模擬請(qǐng)求 (真實(shí)使用把time設(shè)置為0,將resolve傳入異步函數(shù)中) console.log('timein' + time) resolve(); //在異步處理結(jié)束后resolve }, time * 1000) }) } } var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)]; var fn = async function(promiseArr) { for (let i = 0, len = arr.length; i < len; i++) { let currentPromise = promiseArr[i] var result = await currentPromise() } } fn(arr)
通過(guò)打印可以看出如過(guò)是并發(fā)的打印會(huì)是1,2,3,4,5
三、實(shí)現(xiàn)異步并行
并行示意圖:
js并不能并行,我們只是可以思考如何卡在abc都執(zhí)行完成,這里可以用promise.all 來(lái)輕松實(shí)現(xiàn)
const a = new Promise((resolve, reject) => { //模擬異步任務(wù) setTimeout(function() { resolve('a'); }, 1000) }) .then(result => result) .catch(e => { }) const b = new Promise((resolve, reject) => { setTimeout(function() { // resolve('b'); reject('Error in b'); }, 1000) }) .then(result => result) .catch(e => e) Promise.all([a, b]).then(data => { console.log('data', data) }) .catch(e => console.log('erro', e));
這里需要注意的是,all能接受的 resolve reject都行,所以需要每個(gè)自己去處理異常
多個(gè)異步
promise
var createPromise = function(time) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('time', time); resolve(time) }, time * 1000) }) } var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)]; Promise.all(arr).then(data => { console.log('data', data) })
asnyc await
var createPromise = function(time) { return new Promise((resolve, reject) => { setTimeout(() => { console.log('time', time); resolve(time) }, time * 1000) }) } var arr = [createPromise(2), createPromise(3), createPromise(1), createPromise(4), createPromise(5)]; var fn = async function(promiseArr) { let awaitArr = [] for (let i = 0, len = arr.length; i < len; i++) { let currentPromise = promiseArr[i] let result = await currentPromise awaitArr.push(result) } return awaitArr } // async 返回的是一個(gè)promise fn(arr).then(data => { console.log('data', data); })
到此這篇關(guān)于js異步處理方案,js的異步串行與異步并行的文章就介紹到這了,更多相關(guān)js異步處理內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
深入理解JavaScript系列(36):設(shè)計(jì)模式之中介者模式詳解
這篇文章主要介紹了深入理解JavaScript系列(36):設(shè)計(jì)模式之中介者模式詳解,中介者模式(Mediator)是指用一個(gè)中介對(duì)象來(lái)封裝一系列的對(duì)象交互,需要的朋友可以參考下2015-03-03ajax上傳時(shí)參數(shù)提交不更新等相關(guān)問(wèn)題
我感覺(jué)好像這個(gè)上傳插件只在第一次點(diǎn)擊的時(shí)候?qū)嵗?shù)傳給后臺(tái),所以以后值都是不變的,應(yīng)該怎么解決這個(gè)問(wèn)題呢2012-12-12簡(jiǎn)單掌握J(rèn)avaScript中const聲明常量與變量的用法
const和let一樣,也是ES6版本中引入的新關(guān)鍵字,下面我們就通過(guò)例子來(lái)簡(jiǎn)單掌握J(rèn)avaScript中const關(guān)鍵詞聲明常量與變量的用法2016-05-05JavaScript操作HTML DOM節(jié)點(diǎn)的基礎(chǔ)教程
這篇文章主要介紹了JavaScript操作HTML DOM節(jié)點(diǎn)的基礎(chǔ)入門(mén)教程,包括對(duì)節(jié)點(diǎn)的創(chuàng)建修改刪除等操作,還特別提到了其中appendChild()與insertBefore()插入節(jié)點(diǎn)時(shí)需注意的問(wèn)題,需要的朋友可以參考下2016-03-03