91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

一文帶你了解JavaScript中的異步串行

發布時間:2020-11-07 17:05:00 來源:億速云 閱讀:181 作者:Leah 欄目:開發技術

這期內容當中小編將會給大家帶來有關一文帶你了解JavaScript中的異步串行,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

先看題目:

const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const subFlow = createFlow([() => delay(1000).then(() => log("c"))]);

createFlow([
 () => log("a"),
 () => log("b"),
 subFlow,
 [() => delay(1000).then(() => log("d")), () => log("e")],
]).run(() => {
 console.log("done");
});

// 需要按照 a,b,延遲1秒,c,延遲1秒,d,e, done 的順序打印

按照上面的測試用例,實現 createFlow:

  • flow 是指一系列 effects 組成的邏輯片段。
  • flow 支持嵌套。
  • effects 的執行只需要支持串行。

分析

先以入參分析,createFlow 接受一個數組作為參數(按照題意里面的每一項應該叫做 effect),排除掉一些重復的項,我們把參數數組中的每一項整理歸類一下,總共有如下幾種類型:

普通函數:

() => log("a");

延遲函數(Promise):

() => delay(1000).then(() => log("d"));

另一個 flow:

const subFlow = createFlow([() => delay(1000).then(() => log("c"))]);

用數組包裹的上述三項。

實現

先把參數淺拷貝一份(編寫庫函數,盡量不要影響用戶傳入的參數是個原則),再簡單的扁平化 flat 一下。(處理情況 4)

function createFlow(effects = []) {
 let sources = effects.slice().flat();
}

觀察題意,createFlow 并不會讓方法開始執行,需要 .run() 之后才會開始執行,所以先定義好這個函數:

function createFlow(effects = []) {
 let sources = effects.slice().flat();
 function run(callback) {
  while (sources.length) {
   const task = sources.shift();
  }
  callback?.();
 }
}

這里我選擇用 while 循環依次處理數組中的每個 effect,便于隨時中斷。

對于函數類型的 effect,直接執行它:

function createFlow(effects = []) {
 let sources = effects.slice().flat();
 function run(callback) {
  while (sources.length) {
   const task = sources.shift();
   if (typeof task === "function") {
    const res = task();
   }
  }
  // 在所有任務執行完畢后 執行傳入的回調函數
  callback?.();
 }

 return {
  run,
  isFlow: true,
 };
}

這里拿到了函數的返回值 res,有一個情況別忘了,就是 effect 返回的是一個 Promise,比如這種情況:

() => delay(1000).then(() => log("d"));

那么拿到返回值后,這里直接簡化判斷,看返回值是否有 then 屬性來判斷它是否是一個 Promise(生產環境請選擇更加嚴謹的方法)。

if (res?.then) {
 res.then(createFlow(sources).run);
 return;
}

這里我選擇中斷本次的 flow 執行,并且用剩下的 sources 去建立一個新的 flow,并且在上一個 Promise 的 then 方法里再去異步的開啟新的 flow 的 run。

這樣,上面延遲 1s 后的 Promise 被 resolve 之后,剩下的 sources 任務數組會被新的 flow.run() 驅動,繼續執行。
接下來再處理 effect 是另一個 flow 的情況,注意上面編寫的大致函數體,我們已經讓 createFlow 這個函數返回值帶上 isFlow

這個標記,用來判斷它是否是一個 flow。

// 把callback放到下一個flow的callback時機里執行
const next = () => createFlow(sources).run(callback)
if (typeof task === "function") {
 const res = task();
 if (res?.then) {
  res.then(next);
  return;
 }
} else if (task?.isFlow) {
 task.run(next);
 return;
}

看 else if 的部分,直接調用傳入的 flow 的 run,把剩下的 sources 創建的新的 flow,并且把這一輪的 callback 放入到新的 flow 的 callback 位置。在所有的任務都結束后再執行。

定義一個 next 方法,用來在遇到異步任務或者另一個 flow 的時候

這樣,參數中傳入的 flow 執行完畢后,才會繼續執行剩下的任務,并且在最后執行 callback。

完整代碼

function createFlow(effects = []) {
 let sources = effects.slice().flat();
 function run(callback) {
  while (sources.length) {
   const task = sources.shift();
   // 把callback放到下一個flow的callback時機里執行
   const next = () => createFlow(sources).run(callback)
   if (typeof task === "function") {
    const res = task();
    if (res?.then) {
     res.then(next);
     return;
    }
   } else if (task?.isFlow) {
    task.run(next);
    return;
   }
  }
  callback?.();
 }
 return {
  run,
  isFlow: true,
 };
}
const delay = () => new Promise((resolve) => setTimeout(resolve, 1000));
createFlow([
 () => console.log("a"),
 () => console.log("b"),
 createFlow([() => console.log("c")]),
 [() => delay().then(() => console.log("d")), () => console.log("e")],
]).run();

上述就是小編為大家分享的一文帶你了解JavaScript中的異步串行了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

霍州市| 庆城县| 黔东| 木兰县| 上思县| 云南省| 山东省| 安溪县| 浪卡子县| 北安市| 墨玉县| 永登县| 酉阳| 长宁区| 平舆县| 左贡县| 青浦区| 马山县| 武功县| 台湾省| 历史| 科技| 凤翔县| 化州市| 湘潭市| 秭归县| 登封市| 黄浦区| 龙井市| 务川| 安仁县| 福鼎市| 碌曲县| 延川县| 井冈山市| 武强县| 南部县| 白城市| 邮箱| 周口市| 台安县|