promise順序執行,返回結果存放在數組

来源:https://www.cnblogs.com/maskmtj/archive/2018/07/17/9324669.html
-Advertisement-
Play Games

遇到面試的一個編程題:三個返回promise對象的非同步操作,讓你寫一個函數可以將這些操作順序執行,並返回一個數組包含三個非同步對象的結果 非同步對象: 註意:promise對象在實例化的時候就會執行,所以函數都是返回promise對象,這樣執行函數的時候就會執行promise對象中的內容 我們期望的結果 ...


遇到面試的一個編程題:三個返回promise對象的非同步操作,讓你寫一個函數可以將這些操作順序執行,並返回一個數組包含三個非同步對象的結果

非同步對象:

// 非同步函數a
var a = function () {
  return new Promise(function (resolve, reject) {
      console.log("a")
    setTimeout(function () {
      resolve('a')
    }, 1000)
  })
}

// 非同步函數b
var b = function () {
  return new Promise(function (resolve, reject) {
      console.log("b")
    resolve('b')
  })
}

// 非同步函數c
var c = function () {
  return new Promise(function (resolve, reject) {
      console.log("c")
    setTimeout(function () {
      resolve('c')
    }, 500)
  })
}

註意:promise對象在實例化的時候就會執行,所以函數都是返回promise對象,這樣執行函數的時候就會執行promise對象中的內容

我們期望的結果是:

//a
//b
//c
//(3) ["a", "b", "c"]
//done

所以關鍵是怎麼順序執行promise並把結果一個一個塞到數組裡

註意promise對象是不能直接得到resolve傳來的結果的,一般的方式是.then裡面寫resolve的回調函數,所以剛纔的需求可以這樣寫

var mergePromise = async function mergePromise(arr) {
    var mergedAjax = Promise.resolve()
    var data = [] ;
    for(let promise of arr){
        mergedAjax = mergedAjax.then(()=>{
            return promise().then(val=>{
                data.push(val)
            })
        })
    }
    return mergedAjax.then(()=>{
        return data
    })
};

mergePromise([a,b,c]).then(function (data) {
    console.log(data);
    console.log("done");
});

還有這種寫法:

var mergePromise = async function mergePromise(arr) {
    var mergedAjax = Promise.resolve()
    var data = [] ;
    for(let promise of arr){
        mergedAjax = mergedAjax.then((val)=>{
            if(val)data.push(val)
            return promise()
        })
    }
    return mergedAjax.then((val)=>{
        data.push(val)
        return data
    })
};

mergePromise(ajaxArray).then(function (data) {
    console.log(data);
    console.log("done");
});

以上兩種其實是一個then的鏈式調用,最後返回收集了非同步結果的數組

 

這個需求用asnyc await的寫法就比較好看和直觀

async function queue(arr) {
  let data = []
  for (let promise of arr) {
    let res = await promise()
    data.push(res)
  }
  return data
}
queue([a, b, c])
  .then(data => {
    console.log(data)
console.log("done");
});

感覺上是返回了一個data數組,應該會報沒有.then方法的錯誤,然而實際上是返回了一個Promise.resolve(data)

至於為什麼能將resolve的值抽離出來,是應為await是generator的語法糖,比如一個asnyc函數:

async function myfn(arr) {
let res = await a()
console.log(res)
res = await b()
console.log(res)
res = await c()
console.log(res)
}


myfn([a,b,c])

其實等價於自動執行的generator函數

function spawn(genF) {
  return new Promise(function(resolve, reject) {
    const gen = genF();
    function step(nextF) {

      let next;
      try {
        next = nextF();
      } catch(e) {
        return reject(e);
      }
      if(next.done) {
        return resolve(next.value);
      }
      Promise.resolve(next.value).then(function(v) {
          //Promise.resolve(next.value)中next.value是一個promise對象,比如a()生成的
          //Promise.resolve(arg)中arg是一個promise對象時,將會原封不動返回這個對象
        step(function() { return gen.next(v); });//這裡gen.next(v)執行賦值操作 let res = v 也就是為什麼async方法能得到promise中resolve的值
        
      }, function(e) {
        step(function() { return gen.throw(e); });
      });
    }
    step(function() { return gen.next(undefined); });
  });
}

function fn(args) {
  return spawn(function* () {
    let res = yield a()
    console.log(res)
    res = yield b()
    console.log(res)
    res = yield c()
    console.log(res)
  });
}

fn()

 

最後說一下,如果要讓非同步操作併發,可以用promise自帶的all方法


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 最近在協助調研 Apollo 生成的代碼是否有可能跨 Query 共用模型的問題,雖然初步結論是不能,並不是預期的結果,但是在調研過程中積累的一些經驗,有必要記錄下。如果你也對 Graphql 感興趣,不妨先從 Github 的 Graphql API 來切手實踐。 ...
  • 一,效果圖。 二,index.html代碼。 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Todo</title> <meta name="viewport" content="initial-scale=1, maximu ...
  • 今日看到一句話: 基於迴圈的迭代比基於函數的迭代法快8倍,因此有了該篇驗證博客。 驗證代碼如圖: 驗證結果:在數量比較少的時候,無明顯差別,當數量級達到10的4次方時候,for迴圈的效率優勢明顯。 從中學到其他小知識點: 1、es6語法 數組fill,填充數組,註意,如果填充的是對象,則只是一個指針 ...
  • 我們在工作中常常需要監聽某一個屬性值的變化,這個時候我們就需要用到了監聽屬性watch,在這裡我總結watch屬性的三種場景使用希望對你有所幫助: 1.基礎版監聽: 場景如下:輸入框輸入你的年齡,如果年齡在0 15歲提示信息:你還是個小孩,如果年齡在 15 25歲,提示信息:你已經是個少年,如果年齡 ...
  • 本人後端開發碼農一個,公司前端忙的一逼,項目使用的是easyui組件,其自帶的datebox組件使用起來非常不爽,主要表現在 1、自定義顯示格式很麻煩 2、選擇年份和月份用戶體驗也不好 網上有關於和My97DatePicker結合的例子,但感覺也用的不是很爽。 發現國內的layDate體驗非常滿意, ...
  • 1 2 3 4 5 Title 6 7 8 9 10 用戶名: 11 13 14 密&emsp;碼: 15 17 18 性&emsp;別: 19 ... ...
  • 一. html與Controller中的雙向數據綁定 html Controller的雙向數據綁定,在開發中非常常見,也是Angularjs1.x的宣傳點之一,使用中並沒有太多問題。 1.1數據從html流向controller 也就是從 視圖層 流向 模型層 ,原生html中需要使用表單元素(例如 ...
  • 一、變數 1.var關鍵字的弊端 var關鍵字的弊端:1.可以重覆聲明變數;2.無法限制變數修改;3.沒有會計作用域,只有函數作用域。 慣用的解決辦法是將onclick寫進一個匿名函數。 2.let和const關鍵字 let和const關鍵字使得變數不可以被重覆聲明,且變數具有塊級作用域。不同的是, ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...