對Promise的一些深入瞭解

来源:https://www.cnblogs.com/zanzg/archive/2019/03/20/10566081.html
-Advertisement-
Play Games

1.介紹promise和模仿Promise.all和Promise.race promise的設計主要是解決回調地獄(接收結果用回調函數來處理,但必須傳入回調函數)的問題,由一層層嵌套回調函數改為由then來執行。 例如: // callback用於接收返回結果, 非同步方式 fs.readFile( ...


1.介紹promise和模仿Promise.all和Promise.race

promise的設計主要是解決回調地獄(接收結果用回調函數來處理,但必須傳入回調函數)的問題,由一層層嵌套回調函數改為由then來執行。
例如:



// callback用於接收返回結果, 非同步方式
fs.readFile("filePath", callback);
// 還有一種方式
cosnt { promises: fs } = require("fs"); // 用promise包裝fs模塊,已經實現
fs.readFile("filePath").then(callback);

// 由上可看出,promise只是解決了回調函數的調用方式,沒有徹底改變回調函數繼續存在的問題。

promise有三個狀態,分別是pending, resolve,reject。只有resolve或者reject被調用,才會結束。
promise對象可以通過new創建, 結果返回後then和catch方法會調用,resolve和reject會走then方法,catch是捕捉未處理異常的方法(比如:500,404之類)。

值得註意的是,then方法的返回值為promise類型,如果在then中繼續執行非同步操作,則可以在then後面再次寫一個then操作。叫做鏈式調用,例如:



Promise.resolve("success")
.then((res) => "非同步操作")
.then((resSecond) => console.log(resSecond)); // resSecond為“非同步操作”

另外可直接調用resolve狀態或者reject狀態,例如Promise.resolve(),或者Promise.reject()方法。這兩個方法直接返回結果,也可以傳入一個Promise對象或者工廠函數。這兩個函數本質都是內部創建了一個Promise對象,調用resolve或者reject。

現如今很多的非同步請求,非同步執行方式,都在向promise靠攏。提供了很多的便利性。比如:axios,上面提到的fs模塊,等等。我用過angular的subscribe,也是對非同步的一種處理方式。但有點不倫不類。

1.1 模擬非同步操作,用於測試

  
  // 模擬非同步請求
  const suc = function (time: number) {
    return new Promise(resolve => {
      setTimeout(() => {
        // time秒鐘之後返回結果
        resolve("success"); 
      }, time);
    })
  }

  const rej = function (time: number) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        // time秒之後拒絕
        reject("fail"); 
      }, time);
    })
  }
  // 以上代碼也可合併為一個函數,請讀者自行考慮。
  

1.2 Promise的all,race方法模擬

PromiseAll方法內內只接受兩個非同步Promise,算是簡化版了(官網api代碼簡介),能力有限。PromiseRace基本和官網上的差不多。

PromiseRace: 競爭性關係,獲取第一個結果(無論結果resolve或者reject),立即返回。

PromiseAll_2:感覺使用狀態控制這種不是太好啊

  
      // 準確來說,這個方法有缺陷,只要第一個返回,不管對與不對都返回,應該是所有結果都被reject掉才會返回reject,只有一個正確都要返回正確結果。可結合PromiseAll_2看
      function PromiseRace(arrs: Array): Promise<{}> {
        if (arrs.length === 0) return Promise.resolve([]);
    
        return new Promise((resolve, reject)=> {
          arrs.forEach((pro) => {
            Promise.resolve(pro).then(resolve, reject);
          });
        });
      }
  
    // 當所有結果為ture,才會返回ture
    function isAllFulfilled(states: Array): boolean {
      let res: boolean = true;
      states.forEach(state => res = res && state)
      return res;
    }
    
    // 用一種迴圈的方式迭代每個非同步方法,如果不是函數或對象就直接作為結果返回
    function PromiseAll_2(arrs: Array): Promise<{}> {
      if (arrs.length === 0) return Promise.resolve([]);
      const states: Array = Array.from({length: arrs.length}, (item) => item = false);
      
      return new Promise((resolve, reject)=> {
        const result = [];
        arrs.forEach((pro, index) => {
          // 對輸入做一個封裝,如果是常數或者不是promise的這樣就直接返回
          Promise.resolve(pro).then(res => {
            states[index] = true;
            result[index] = res;
            if (isAllFulfilled(states)) resolve(result);
          }, err => reject(err));
        });
      });
    }

    function PromiseAll(one: Promise, two: Promise): Promise<{}> {
        return new Promise((resolve, reject) => {
          let twoRes = null;
          let oneRes = null;
          // 基於兩個非同步互相檢測,官網那個有點看不大明白。各位有什麼好的代碼建議不妨評論說一下
          one.then((res) => {
            oneRes = res;
            if (twoRes) resolve([oneRes, twoRes]);
          }, (err) => reject(err));
    
          two.then((res) => {
            twoRes = res;
            if (oneRes) resolve([oneRes, twoRes]);
          }, (err) => reject(err));
        });
   }
    
  PromiseAll(suc(1000), rej(2000)).then((res) => {
    console.log(res);
  }).catch((err) => console.log(err));
  

1.3 小工具。

  1. 使用promisify對settimeout做個封裝,單純只是延遲執行



    const util = require("util");
    // 封裝settimeout延遲執行
    const delay = util.promisify(setTimeout); // 用作延遲執行,一般在await的時候用

    用例:
    async function test() {
    await delay(1000); // 延遲一秒執行
    }

  2. async簡單介紹


    async徹底解決了非同步操作回調函數問題。
    只需使用await關鍵字,就會等待非同步操作執行完畢才會繼續執行後續代碼。把非同步操作
    變為同步操作。


// 代碼
async function test() {
const { data } = await axios.get("http://www.baidu.com"); // { data }為解構賦值
// do something
}

// 不用async
function test() {
axios.get("http://www.baidu.com").then((res) => {
console.log(res.data);
//do something
});
}

// 對比以上結構,async函數的同步會帶來很大的方便,但在載入網頁的時候可能需要等待。
// 如果不希望頁面卡頓,採用非同步還是比較好的。

2. 每周分享

  1. 前端框架和es的一些變化,這裡面介紹的是前端中最近的一些框架或者基礎性知識。
  2. nginx的基礎入門,對nginx的一個用法基本介紹。
  3. 阿裡AI labs研發“智能防騷擾電話技術”,當接聽到騷擾電話時,可以轉到機器人接聽。我試了一下,聽得我一愣一愣的,還以為真的和人工客服聊天。具體想體驗的可以在支付寶搜索天貓精靈。不過這項功能可能會給你帶來困擾,如果你主動掛斷電話,就會立馬改為由智能機器人接聽,如果是你女票打來的,你有事情馬上掛斷,後果不堪設想!好在可以關閉或者打開。玩玩可以,可不要貪杯啊。(>_<)
    ----

資料


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

-Advertisement-
Play Games
更多相關文章
  • 有些時候為了強調某些文字,需要使用一些比較特別的字體,CSS中現在也可以比較方便的引入字體了,如下: 其中font-family就是之後使用時候的字體名稱了,如此一來CSS中就可以直接使用本地的字體了,如下: 如果需要引用線上字體,首先需要找到線上字體,國內推薦谷歌字體,雖然裡面的中文字體不知道什麼 ...
  • 進行樣式修改,初步修改的內容 #home{width:90%;position:relative;}#blogTitle a{color:#fff; text-shadow:1px 1px 5px #ccc;}#blogTitle h2{color:#ffe;font-weight:700;text ...
  • 剛入職的時候看到公司用的HTML日誌生成工具附帶的Panel,工具不夠用,找個Fail還要找半天,於是自己琢磨著添磚加瓦。以前也是個半吊子前端工程師,現在可倒好,想要改頁面卻連頁面生成的模板在哪裡都不知道,只有通過改動JavaScript才能實現對頁面的修改。 固然,操作DOM有原版的 一族,可是它 ...
  • vue的組件,過濾器,監聽屬性,生命周期函數 vue有局部組件和全局組件,這個組件後期用的會比較多,也是非常重要的 局部組件 template與components屬性結合使用掛載 ...
  • 最簡單的解決辦法,不影響其他操作,給提交按鈕增加 type="button" 屬性 完美解決 ...
  • 近幾年,職場上歷經的激蕩與陣痛,比以往來得似乎更為猛烈一些。 近幾年,職場上歷經的激蕩與陣痛,比以往來得似乎更為猛烈一些。 近幾年,職場上歷經的激蕩與陣痛,比以往來得似乎更為猛烈一些。 近幾年,職場上歷經的激蕩與陣痛,比以往來得似乎更為猛烈一些。 2016年,亞馬遜員工平均31歲,谷歌員工均齡30歲 ...
  • 先判斷有沒有,沒有再創建,有就跳過 先判斷有沒有,沒有再創建,有就跳過 <input type="button" value="按鈕" id="btn"/> <div id="dv"></div> my$("btn").onclick=function () { //判斷這個按鈕的子元素是否存在 i ...
  • Web前端 Vue.js必備框架(五) 頁面組件,商品列表組件,詳情組件,購物車清單組件,結算頁組件,訂單詳情組件,訂單列表組件。 下載: 使用 腳手架搭建項目 引入 ,它是為 開發的狀態管理模式,採用集中式存儲管理應用的所有組件的狀態,以相應的規則保證狀態以一種可預測的方式發生變化。 計算屬性 數 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...