nodejs中的promise基本操作


1.為什么要使用promise

 

/*
需求:異步的按順序去讀取1.txt、2.txt、3.txt文件的內容
假設 1.txt內容為111 、2.txt內容為222、3.txt內容為333
*/
var  fs = require('fs');、
 fs.readFile('./files/1.txt','utf8',function(err,data){
   if(err){
     throw err;
   }
   console.log(data);
 })

 fs.readFile('./files/1.txt','utf8',function(err,data){
   if(err){
     throw err;
   }
   console.log(data);
 })

 fs.readFile('./files/1.txt','utf8',function(err,data){
   if(err){
     throw err;
   }
   console.log(data);
 })
/*
 結果:111 222 333。(好像滿足需求啊)
*/

/* 
問題:上面的代碼雖然正常按照順序讀取了文件,因為文件的內容都非常少,io讀取耗時少,但當2.txt內容較多時候,2.txt的內容是最后輸出的。因為他們都是異步操作,不知道誰先讀取完。 這得取決於異步任務IO的耗時。
*/

/*
常規解決辦法:
在第一個異步任務讀取成功之后再讀取第二個異步任務,
第二成功后,在讀取第三個異步任務
*/
//讀取第一個異步任務
fs.readFile('./files/1.txt','utf8',function(err,data){
  if(err){
    throw err;
  }
  console.log(data);
  //讀取第二個異步任務
  fs.readFile('./files/2.txt','utf8',function(err,data){
    console.log(data);
    //讀取第三個異步任務
    fs.readFile('./files/3.txt','utf8',function(err,data){
      console.log(data);
    })
  })
})

/* 
結果: 111 222 333 (這必須按照順序輸出的,結果杠桿的)  
*/

/*
問題:
以上按照順序執行多個異步任務產生的問題:`回調地獄`問題(層層包裹進行回調,代碼也不夠優雅)
*/

/* 
解決辦法:采用es6,提供的promise來解決上述產生的問題。
*/

2.Promise基本使用

promise介紹:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise

 


//簡單說promise就是用來執行異步任務的,可以解決上面所說的回調地獄問題,
//語法:new Promise(function(callback){})
var  fs = require('fs');
var promise = new Promise(function(resolve,reject){
  //這里就是寫異步的代碼,只要new  Promise操作,就會立刻執行這里的代碼
  //兩個參數 resolve 異步執行成功的回調函數,reject異步執行失敗的回調函數
  fs.readFile('./files/1.txt', 'utf8', function (err, data) {
    if (err) {
      throw err;
    }
    console.log(data);
  })
});
//運行結果:111

3.promise參數resolve和reject

兩個參數

  • resolve 異步執行成功的回調函數,
  • reject異步執行失敗的回調函數

 


var fs = require('fs');
var promise = new Promise(function (resolve, reject) {
  //兩個參數: resolve 成功的回調函數名  , reject失敗的回調函數名
  fs.readFile('./files/111.txt', 'utf8', function (err, data) {
    if (err) {
      //說明失敗了,要執行失敗的回調函數
      reject(err);
    } else {
      //成功的邏輯
      resolve(data);
    }
    //等價於
    // err ? reject(err) : resolve(data);
  })
});

//new Promise返回的是一個promise對象,
//這個對象有一個方法叫做then,在其原型對象上
//通過這then方法可以指定成功和失敗的回調函數
//語法:promise.then(successCallback,errorCallback);
promise.then(function (data) {
  //then第一個函數是成功的回調,參數是resolve(err)中的data
  console.log('成功:' + data); // 若成功,運行結果:成功:111
}, function (err) {
  //then第二個函數是失敗的回調函數,參數是reject(err)中的err錯誤對象
  console.log('失敗:' + err);
});

4.解決回調地獄問題

 


//封裝一個異步讀取文件的內容的函數
//此函數返回對應異步任務的promise對象
function getFileByPath(path) {
  return new Promise(function (resolve,reject) {
    fs.readFile(path, 'utf8', function (err, data) {
      if(err){
        reject(err);   //失敗
      }else{
        resolve(data);    //成功
      }
    })
  });
}

//由於then通過getFileByPath返回的是一個promise對象,所以可以繼續.then串聯調用(鏈式調用)
getFileByPath('./files/1.txt')
.then(function(data){
  console.log("成功:"+data);
  return getFileByPath('./files/2.txt');
},function(err){
  console.log("失敗:"+err);
  return getFileByPath('./files/2.txt');
}) 
.then(function(data){ 
  console.log("成功:"+data);
  return getFileByPath('./files/3.txt');
},function(err){
  console.log("失敗:"+err);
  return getFileByPath('./files/3.txt');
})
.then(function(data){
  console.log("成功:"+data);
},function(err){
  console.log("失敗:"+err);
});

注意:上面一定會保證按照.then的順序去執行異步的代碼,
如果某個異步任務有錯誤則會觸發對應then的第二個錯誤的回調函數。即每個promise對象都有對應的錯誤回調,對其他的promise不影響。畢竟promise的英文翻譯就是保證。

5.catch的使用

catch也是在Promise.prototype原型上定義的。

 

image.png

 

需求:如果多個promise任務,其中有一個失敗了,則終止后面的所有的promise執行

 

getFileByPath('./files/1.txt')
.then(function(data){
  console.log("成功:"+data);
  return getFileByPath('./files/2.txt');
}) //上面的then通過getFileByPath返回的是一個promise對象,所以可以繼續.then串聯調用(鏈式調用)
.then(function(data){ 
  console.log("成功:"+data);
  return getFileByPath('./files/3.txt');
})
.then(function(data){
  console.log("成功:"+data);
})
.catch(function(err){   
  // catch作用: 上面所有的promise如果其中一個有錯誤,
  //則終止下面所有的promise執行,且直接進入到catch中獲取對應promise的異常錯誤信息
  console.log('catch:'+err);
})

注意:如果在then中定義了錯誤回調則不會進入到上面的catch中,這是因為promise對象指定了對應的錯誤處理回調。

6 then-catch-finally

 


var fs = require('fs');
var promise = new Promise(function (resolve, reject) {
  //兩個參數: resolve 成功的回調函數名  , reject失敗的回調函數名
  fs.readFile('./files/11.txt', 'utf8', function (err, data) {
    if (err) {
      //說明失敗了,要執行失敗的回調函數
      reject(err);
    } else {
      //成功的邏輯
      resolve(data);
    }
  })
});

//new Promise返回的是一個promise對象,
//這個對象有一個方法叫做then,在其原型對象上
//通過這then方法可以指定成功和失敗的回調函數
//語法:promise.then(successCallback,errorCallback);
promise.then(function (data) {
  //then第一個函數是成功的回調,參數是resolve(err)中的data
  console.log('成功:' + data); // 若成功,運行結果:成功:111
}).catch(function(err){
  //then第二參數錯誤回調換成這里catch也行,兩者選其一
  console.log('err');
}).finally(function(){
  //無論失敗成功都會執行
  console.log('完成');
})

7. Promise.all靜態方法的使用

參照:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Promise#%E6%96%B9%E6%B3%95
需求:把所有的promise執行成功的結果保存在一個數組中。。

 

var promise1 = getFileByPath('./files/1.txt');
var promise2 = getFileByPath('./files/2.txt');
var promise3 = getFileByPath('./files/3.txt');

//執行多個異步任務,
Promise.all([promise3,promise1,promise2]).then(function(data){
  console.log(data); 
},function(err){
  console.log('錯誤了:'+err);
})
//Promise.all尤其是在一個頁面上發起多個ajax請求的時候,如果要同時保證他們成功,則使用Promise.all是最合適不過的了。其中一個失敗則也可以在then的第二個回調做失敗的邏輯。

若都成功,運行結果:['333','111','22']

注意:Promise.all的成功結果是返回一個數組,且數組中數據的結果順序與Promise.all數組的傳參順序是一樣的。

 


免責聲明!

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



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