對Promise的一些深入了解


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); // 延遲一秒執行 
       }
  
  1. 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研發“智能防騷擾電話技術”,當接聽到騷擾電話時,可以轉到機器人接聽。我試了一下,聽得我一愣一愣的,還以為真的和人工客服聊天。具體想體驗的可以在支付寶搜索天貓精靈。不過這項功能可能會給你帶來困擾,如果你主動掛斷電話,就會立馬改為由智能機器人接聽,如果是你女票打來的,你有事情馬上掛斷,后果不堪設想!好在可以關閉或者打開。玩玩可以,可不要貪杯啊。(>_<)

資料


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM