Promise初體驗

Promise是什麼

JS就是操縱對象上的屬性和要領,關於一個對象,想要相識,我們可以直接從其身上的屬性和要領入手;直接運用
console.dir(對象)打印出來

《Promise初體驗》

從上面打印出來的屬性和要領,可以看到Promise是一個組織函數,有屬於本身私有的all,reject,resolve,rece等要領,也有原型上面的,屬於實例對象挪用的要領then,catch

// Promise內里傳入一個函數範例的參數,這個函數範例的參數吸收兩個參數resolve reject
var p=new Promise(function(resolve,reject){
     // 異步操縱
     setTimeout(function(){
         console.log('icessun');  // 兩秒以後打印出icessun
         resolve('icessun2'); // resolve是勝利后的回調函數 內里的icessun2是傳入的參數
      },2000)
  });
// 那末p是一個實例對象,可以運用then要領(Promise原型上面的要領)
p.then(function(){
    console.log(arguments);  // 會打印出一個類數組 ['icessun2']
    
 })
p.then(function(data){
    console.log(data);  // 會打印出icessun2 data吸收了resolve內里的參數
 })

關於上面這段代碼,起首new一個實例對象賦值給pPromise的組織函數接收一個參數,是函數;而且傳入兩個參數:resolve,reject,離別示意異步操縱實行勝利后的回調函數和異步操縱實行失利后的回調函數;然後內里設置一個定時器setTimeout,開啟一個異步操縱,兩秒后輸出icessun,而且挪用resolve要領,注重一個細節

上面的代碼,只是
new了一個對象實例,並沒有挪用,就實行了;關於這個狀況,平常是把其嵌套在一個函數內里,防備馬上實行,在須要的時刻去運轉這個函數。

p 是一個實例對象,可以運用then要領,其內里的函數是關於resolve或許reject的挪用的表現,可以吸收resolve,reject傳入的參數

function icessun(){
   var p=new Promise(function(resolve,reject){
        setTimeout(function(){
           console.log('icessun');
           reslove('icessun2');
        },2000);
    });
  return p; // 返回p實例,使其可以運用Promise原型上面的要領
}
icessun(); // 挪用實行icessun函數 獲得一個Promis對象

// 也可以直接如許挪用
icessun().then(function(data){
console.log(data); // icessun2
// 一些其他的操縱
// .....
});

經由過程上面的代碼,曉得then內里的函數就是常常說的回調函數callback,在icessun這個異步使命實行完成后被實行。把回調函數寫法分離出來,在異步操縱實行完后,用鏈式挪用的要領實行回調函數,關於多層回調來講,非常的輕易,可以繼承在then的要領中繼承寫Promise對象並返回,繼承挪用then來舉行回調操縱,這就是Promise的作用。

鏈式操縱

從上面看,
Promise關於多層回調,可以簡化其寫法,使得越發的語義化;然則
Promise的精華在於其鏈式操縱,通報
狀況,保護狀況的體式格局使得回調函數可以實時的挪用。翻開
Promise的準確場景是如許:

function runAsync1(){
  var p=new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('實行完成1')
            resolve('icessun1');
         },2000);
   });

   return p; // 返回p實例對象
}
function runAsync2(){
  var p=new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('實行完成2')
            resolve('icessun2');
         },2000);
   });

   return p; // 返回p實例對象
}
function runAsync3(){
  var p=new Promise(function(resolve,reject){
        setTimeout(function(){
            console.log('實行完成3')
            resolve('icessun3');
         },2000);
   });

   return p; // 返回p實例對象
}

// 準確的翻開Promise的要領
runAsync1()
           .then(function(data){
               console.log(data);
               return runAsync2();
           })
           .then(function(data){
                console.log(data);
                return runAsync3();
            })
            .then(function(data){
                console.log(data);
             })

如許可以根據遞次,每隔兩秒輸出每一個異步回調中的內容,運轉結果:

《Promise初體驗》
固然我們可以直接return數據而不是Promise對象,在背面的then要領就可以直接吸收到數據,以下:

// 準確的翻開Promise的要領
runAsync1()
           .then(function(data){
               console.log(data);
               return runAsync2();
           })
           .then(function(data){
                console.log(data);
                return '我是直接返回的數據';
            })
            .then(function(data){
                console.log(data);
             })

《Promise初體驗》

reject的用法

前面我們說了
resolve是實行勝利的回調,那末
reject就是實行失利的回調,將
Promise的狀況設置為
rejected,如許就可以在
then內里獲取到,實行失利狀況下的回調。

function getNumber(){
   var p=new Promise(function(resolve,reject){
      setTimeout(function(){
          var num=Math.ceil(Math.random()*10); // 天生1-10 之間的隨機數 Math.ceil(): 大於或即是給定数字的最小整數
          if(num<=5){
            resolve(num);
           }else{
             reject('数字太大了')
            }
        },2000);
    });
   return p;
}

getNumber()
          .then(function(data){
               console.log('resolved');
               console.log(data);
            },function(reason,data){
                  console.log('resolved');
               console.log(reason); // 数字太大
                console.log(data); // undefined
              });

getNumber()函數實行後會湧現兩種狀況,要麼大於5,要麼小於5,在then中傳入了兩個參數,第一個是對應resolve的回調,第二個是對應reject的回調。

catch的用法

看到這個要領,就會想到瀏覽器處置懲罰非常的
try...catch()要領,有毛病進入
catch要領,不阻斷順序的實行,實在這個要領也是來處置懲罰毛病的,用來指定
reject的回調,防備順序毛病,阻斷背面順序的實行,使其可以繼承實行。

getNumber()
           .then(function(data){
              console.log('resolve');
              console.log(data);
            })
            .catch(function(data){
               console.log('reject');
               console.log(data);
             })

其結果和上面在then內里寫兩個函數是一樣的,這個寫法的優點是當代碼湧現了毛病的時刻,不會阻斷順序的實行,而是進入catach要領。

all要領的運用

Promise對象上的要領,實例不能運用,只能這個對象運用,這個要領經由過程了
并行實行異步操縱的才能,而且在一切的異步操縱完成后才實行回調

Promise
       .all([runAsync1(),runAsync2(),runAsync3()])
       .then(function(results){
          console.log(results);
        });

Promise.all來實行前面的三個異步的函數,all()吸收一個數組參數,內里的實行終究都返回Promise對象,只要等三個異步操縱都實行完成后才會進入到then內里,all會把一切的異步操縱的結果放在一個數組中傳給then,就是上面的results,代碼的輸出結果:

《Promise初體驗》

有了all,可以并行實行多個異步操縱,而且在一個回調中處置懲罰一切的返回數據,一個經常使用的場景:遊戲類的素材比較多的運用,翻開網頁的時刻,預先加載須要用到的種種資本,如圖片,flash以及種種靜態文件,比及一切都加載完成,我們再舉行頁面的初始化。

race的用法

這個也是
Promise類上面的私有要領,關於前面的
all要領來講是:誰的順序實行的慢,就等誰實行完才回調。然則關於
race來講:誰的順序實行的快,就以它為規範挪用回調函數,其用法基本上是一樣的,把上面
runAsync1函數的耽誤改成1秒

Promise
      .race([runAsync1(),runAsync2(),runAsync3()])
       .then(function(results){
         console.log(results);
        });

這三個 異步操縱同樣是并行實行的,然則比及1秒后,runAsync1已實行終了,因而then接收到了實行終了的回調,輸出回調結果;與此同時,runAsyn2runAsyn3也繼承實行,輸出了實行的結果,然則不能回調then要領。

《Promise初體驗》

這個要領的運用場景許多,比方可以用race給某個異步要求設置超時時候,而且在超時后實行響應的操縱:

// 要求某個圖片資本 異步
function requestImg(){
    var p=new Promise(function(resolve,reject){
        var img=new Image(); // 建立一個圖片對象實例 Image背面沒有參數的時刻,括號可以省略
        img.src='xxxxx'; // 給對象上面的屬性設置屬性值
        img.onload=function(){
           resolve(img); // 圖片勝利加載的時刻,把img對象作為參數傳到回調函數內里
         }
     });
   return p; // 當挪用這個函數的時刻可以運用then要領
 }

 // 延時函數 給要求計時
 function timeout(){
    var p=new Promise(function(resolve,reject){
         setTimeout(function(){
            reject('圖片要求超時');
          },4000);
     });
     return p;
  } 

Promise.race([requsetImg(),timeout()])
       .then(function(results){
           console.log(results); // 圖片勝利加載會把圖片的途徑打印在控制台
        })
        .catch(function(reason){
         console.log(reason); // 失利會提醒加載失利
         })

requestImg函數會異步要求一張圖片,圖片地點寫錯,肯定是沒法加載圖片要求。timeout函數是一個延時4秒的異步操縱,把這兩個返回Promise對象的函數放到race內里,假如4秒內圖片要求勝利,就會回調then要領,實行一般的流程,不然進入catch要領,顯現圖片要求超時。

《Promise初體驗》

《Promise初體驗》

    原文作者:icessun
    原文地址: https://segmentfault.com/a/1190000014935141
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞