ES6 promise 解惑

promise 的由來

有時候我們做ajax請求,可能會遇到以下這種情況
requsetA > requsetB > requestC
requestB的請求依賴requestA的數據,requestC的請求依賴requestB的數據。在沒有異步編程的概念那時,我們往往只能通過回調函數的方法去解決這個問題。

     requestA(function(res){
            requestB(function(res){
                  requestC(function(res){
                        //do something
                  })
            })
      })

其實也不是很難看,比較有層次感,哈哈。。。

然而,實際情況并不會想現在那樣那么簡單,你可能還需要將requestA的數據進行一些處理才能夠傳給requestB,requestB請求回來的數據,又得做一些處理才能傳給requestC,那么這就會變成一團巨大的函數體,可讀性十分糟糕。

所以就有了promise對象的出現,它是專治多重依賴的異步操作的。

我們可以使用promise來改寫以上代碼

promise走起

//定義 一個promise對象,進行requestA異步請求
  let pro = new Promise((resolve,reject)=>{
       requestA({//一些配置})
       //jquery 1.8+ 新寫法,success已經過時
      .done((data)=>{
          //resolve方法將參數傳遞給下一個回調函數
          resolve(data)  
      })
      .error((err)=>{
          reject(err);  
      })
  })

 //進行requestB異步請求
let requestB = (res)=>{
    let pro1 = new Promise((resolve,reject)=>{
      reqb({//一些配置})
      .done((data)=>{
            console.log(res);
            resolve(data);
      })
      .error((err)=>{
          reject(err);  
      })
  })

 //進行requestC異步請求
let requestC = (res)=>{
    let pro2 = new Promise((resolve,reject)=>{
      reqc({//一些配置})
      .done((data)=>{
            console.log(res);
            console.log(data);
      })
      .error((err)=>{
          reject(err);  
      })
  })

//然后 ,使用優雅的方式進行異步回調

pro.then(requestB)
   .then(requestC)

promise與傳統的ajxa同步請求

讓我們先來做一個實驗

  1. 寫段簡單的服務端代碼,以php為例
   <?php
      //睡眠5秒,模擬真實網絡請求環境
       sleep(5);
      //防止跨域請求
       header('Access-Control-Allow-Origin:*');
       header('Access-Control-Allow-Methods:POST,GET');
        //獲取前端get請求參數,返回
       $usript = $_GET['keyword'];
       echo $usript;
   ?>
  1. 封裝原生ajax請求
//使用 ES6賦值解構語法
 function ajax({url,test,bool,callback}){
            var ajax = new XMLHttpRequest();
            ajax.onreadystatechange = function() {
                if (ajax.readyState == 4 && ajax.status == 200) {
                    var response = ajax.responseText;
                    Object.prototype.toString.call(callback) === '[object Function]' && callback(response)
                    test && console.timeEnd(test)
                }
            };
            ajax.open("GET", url, bool);
            ajax.setRequestHeader("Content-type", "text/plain");
            ajax.send();
        }
  1. 編寫同步測試代碼
//使用chrome控制臺api 的console.time()進行計時操作
ajax({
            url:"http://192.168.1.105/index.php?keyword=123",
            bool:false,
            callback:(res)=>{
                ajax({
                    url:"http://192.168.1.105/index.php?keyword=123",
                    test:'sync test',
                    bool:false,
                    callback:(data) => console.log(`${res} -requestA: ${data}`)
                })
            }
        })
console.log('hello promise')

結果

123
test.html:15 sync test: 10014.349ms
hello promise

結果顯而易見ajax同步請求會阻塞javascript運行,導致其后的代碼阻塞等待,嚴重拖低性能

  1. 編寫異步測試代碼
   console.time('async test')
        let pro = new Promise((resolve,reject)=>{
            ajax({
                url:"http://192.168.1.105/index.php?keyword=123",
                bool:true,
                callback:(data)=>{
                    if(data){
                        resolve(data);
                    }else{
                        reject('請求錯誤!')
                    }
                }
            })
        })

        let requestA = (res)=>{
            let resA = new Promise((resolve,reject)=>{
            ajax({
                url:"http://192.168.1.105/index.php?keyword=123",
                bool:true,
                callback:(data)=>{
                    if(data){
                        console.log(`${res} -requestA: ${data}`)
                    }else{
                        reject('請求錯誤!')
                    }
                },
                test:'async test'
            })
        })
    }
    pro.then(requestA);

    console.log('hello promise')

結果

hello promise
test.html:62 123 -requestA: 123
test.html:15 async test: 10022.117ms

promise是異步的,引擎執行代碼的時候會先將異步代碼掛起,先去執行其他代碼,等待上一個請求結束再回過頭來執行下一個請求的代碼,所以,雖然promise和ajax同步請求用的時間一樣多,也可以說promise就是在做同步請求,但是promise本身是異步的,并不會阻塞代碼,所以你可以看到先打印出了hello promise

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容