bl双性强迫侵犯h_国产在线观看人成激情视频_蜜芽188_被诱拐的少孩全彩啪啪漫画

JS下大批量異步任務按順序執(zhí)行的示例分析

這篇文章主要介紹了JS下大批量異步任務按順序執(zhí)行的示例分析,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)公司服務項目包括來鳳網(wǎng)站建設、來鳳網(wǎng)站制作、來鳳網(wǎng)頁制作以及來鳳網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構等提供互聯(lián)網(wǎng)行業(yè)的解決方案,來鳳網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到來鳳省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!

前言

最近需要做一個瀏覽器的, 支持大體積文件上傳且要支持斷點續(xù)傳的上傳組件, 本來以為很容易的事情, 結果碰到了一個有意思的問題:

循環(huán)執(zhí)行連續(xù)的異步任務, 且后一個任務需要等待前一個任務的執(zhí)行狀態(tài)

這么說可能有點空泛, 以我做的組件舉例:

這個組件本意是為了上傳大體積視頻, 和支持斷點續(xù)傳, 因為動輒幾個G的視頻不可能直接把文件讀進內(nèi)存, 只能分片發(fā)送(考慮到實際網(wǎng)絡狀態(tài), 每次發(fā)送大小定在了4MB), 而且這么做也符合斷點續(xù)傳的思路.

組件工作流程如下:

  1. 選定上傳文件后, 從H5原生upload組件里取得文件的blob對象  (同步)

  2. 通過blob對象的slice方法把文件切片  (同步)

  3. 新建一個Filereader對象, 通過Filereader的readAsArrayBuffer方法讀取步驟2中生成的slice  (異步)

  4. 如果步驟3的buffer讀取成功(通過監(jiān)控Filereader的onload事件), 則ajax發(fā)送步驟3中的buffer  (異步)

  5. 如果ajax發(fā)送成功, 且服務器儲存完成, 會向客戶端發(fā)回一個成功狀態(tài)碼, 如果ajax的response中存在這個狀態(tài)碼, 則進行下一次切片發(fā)送  (異步)

從組件工作流程可以發(fā)現(xiàn), 3,4,5中的連續(xù)異步任務, 必須要按順序進行, 且每一步任務間存在相互依賴, 最后還要對這些步驟進行多次循環(huán).

如果只是處理單次的連續(xù)異步任務, 通過promise鏈式調用即可, 但是要循環(huán)執(zhí)行這樣的連續(xù)異步任務讓我想了很久.

后來google了很久也沒發(fā)現(xiàn)解決方案, 無奈下閉門造車了2天, 想出了3套方案, 權當拋磚引玉, 希望各位給出更好建議

3套方案的核心思想相同, 類似觀察者模式, 來控制循環(huán)的進行, 區(qū)別在于循環(huán)的實現(xiàn)不同, 實際上這3套方案也是我自我否定的過程, 不斷思考更好的方法, 整個組件代碼略長, 在此只挑出問題相關部分, 且省略錯誤處理部分

方案1

依然以上傳組件舉例

//循環(huán)狀態(tài)標記,0為初始狀態(tài),1為正常,2為出錯
let status = 0;

/* 新建Filereader,讀取文件切片,返回一個promise
* 把讀取成功的arraybuffer通過reslove傳出
*/
const createReader = ()=> {
 return new Promise ((reslove, reject)=> {
  let reader = new Filereader();
  ...
  reader.onload = ()=> {
   reslove(reader.result)
  }
  reader.onerror = ()=> reject()
 })
}

// ajax發(fā)送createReader方法讀取到的Buff
const createXhr = ()=> {
 const xhr= new XMLHttpRequest();
 return new Promise ((reslove, reject)=> {
  ...
  xhr.onreadystatechange= ()=> {
   ...
   //如果readyState == 4,status == 200且服務器的狀態(tài)碼存在,更改全局標記為1
   status = 1;
   reslove()
  }
 })
}

//每一輪循環(huán)開始前都檢查一次全局狀態(tài)標記
const checkStatus = ()=> {
 ...
 if (status == 1) {
  loop()
 }
}

//循環(huán)過程的鏈式調用
const loop = ()=> {
 createReader().then(()=> createXhr()).then(()=> checkStatus());
}

方案1是基于初見問題的'想當然'解決方法, 碰到異步任務就promise, 這樣的循環(huán)長鏈調用, 寫法不優(yōu)雅, 且錯誤調試異常麻煩, 更爆炸的是因為閉包問題, 在循環(huán)執(zhí)行中這些內(nèi)存難以回收, 內(nèi)存消耗急劇增加, 只能等待循環(huán)執(zhí)行完成

方案2

徹底引入觀察者模式, 構造一個簡單的EventEmitter, 通過event.on, event.emit的形式完成循環(huán)

//模仿node.js的EventEmitter
class EventEmitter {
 constructor() {
  this.handler = {};
 }
 on(eventName, callback) {
  if (!this.handles){
   this.handles = {};
  }
  if (!this.handles[eventName]) {
   this.handles[eventName] = [];
  }
  this.handles[eventName].push(callback);
 }
 emit(eventName,...arg) {
  if (this.handles[eventName]) {
   for (var i=0;i<this.handles[eventName].length;i++) {
    this.handles[eventName][i](...arg);
   }
  }
 }
 }

let ev= new EventEmitter();
...
//監(jiān)聽createReader事件,如果讀取buffer成功就觸發(fā)toajax事件來上傳切片
ev.on('createReader', ()=> {
 let reader = new Filereader();
 ...
 reader.onload = ()=> {
  ev.emit('toajax')
 }
})

//監(jiān)聽toajax事件,如果上傳成功,就觸發(fā)createReader事件開始讀取下一切片
ev.on('toajax', ()=> {
 let xhr= new XMLHttpRequest();
 ...
 xhr.onreadystatechange = ()=> {
 //如果readyState == 4,status == 200且服務器的狀態(tài)碼存在
  ev.emit('createReader')
 }
})

方案2徹底貫徹'事件', 代碼語義更自然, 錯誤調試也比方案1更為簡單, 但內(nèi)存泄漏問題依然存在

方案3

方案3, 回歸方案1的狀態(tài)管理方式, 但是通過setInterval方法來實現(xiàn)循環(huán).

//全局狀態(tài)標記
let status = 0;

//讀取切片
const createReader = ()=> {
 let reader = new Filereader();
 ...
 reader.onload = ()=>status = 1
}

//上傳切片
const createXhr = ()=> {
 let xhr= new XMLHttpRequest();
 ...
 xhr.onreadystatechange = ()=> {
  ...
  //如果readyState == 4,status == 200且服務器的狀態(tài)碼存在
  status = 2
 }
}

/* 設置一個間隔時間極短的計時器,根據(jù)status決定下一步的任務,
* 上傳完成后定時器自動清除自己
* 另外有判斷文件是否上傳完成的方法,這里就不寫了
*/
let timer = setInterval(()=> {
 if (status == 2) {
  createReader();
 } else if (status == 1) {
  createXhr();
 } else if (status == 3) {
  clearInterval(timer);
 }
},10)

不可否認, 方案3看上去很low, 如果追求極致的執(zhí)行效率, 方案3無疑是最蠢的辦法, 但是方案三相當于把異步任務轉化為了同步任務, 語義簡潔, 且沒有上面2種方法的內(nèi)存泄漏問題.

方案3本質上是把while (true)改寫成了setInterval, 因為while true會阻塞線程, 各種異步事件的回調也會被一同阻塞, 所以選擇了setInterval

感謝你能夠認真閱讀完這篇文章,希望小編分享的“JS下大批量異步任務按順序執(zhí)行的示例分析”這篇文章對大家有幫助,同時也希望大家多多支持創(chuàng)新互聯(lián),關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,更多相關知識等著你來學習!

分享題目:JS下大批量異步任務按順序執(zhí)行的示例分析
分享網(wǎng)址:http://vcdvsql.cn/article6/pphsog.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供企業(yè)建站、用戶體驗、建站公司、App設計靜態(tài)網(wǎng)站、網(wǎng)站內(nèi)鏈

廣告

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

外貿(mào)網(wǎng)站建設