文章出處

最近一段時間一直在看Node.js,在開發過程中經常要調用一些異步接口,通常在接口的最后一個參數會傳入一個回調函數,可以用來處理異常,非異常情況。大致模式如下:

1 var fs = require(“fs");
2 fs.readFile(filename, "binary", function(err, file){
3     if(err){
4         //異常情況
5    }else{
6        //正常情況
7     }
8 });            

但是,這種寫法遇上比較復雜的邏輯時,就很容易出現 callback hell的問題。

Node.js需要按順序執行異步邏輯時一般采用后續傳遞風格,也就是將后續邏輯封裝在回調函數中作為起始函數的參數,逐層嵌套。這種風格雖然可以提高 CPU利用率,降低等待時間,但當后續邏輯步驟較多時會影響代碼的可讀性,結果代碼的修改維護變得很困難。根據這種代碼的樣子,一般稱其 為"callback hell"

對異步接口的處理方式都是依賴于Promise,對于上篇文章講到的Fetch,直接返回Promise.

如何將callback接口變成Promise接口?

var promisify = function promisify(fn, receiver) {
    return function() {
          for(var _len = argument.length, args = Array(_len), _key = 0; _key<_len; _key++) {
               args[_key] = arguments[_key];
          }
    
        return new Promise(function (resolve, reject) {
          fn.apply(receiver, [].concat(args,[function(err, res){
             return err ? reject(err) : resolve(res);
          }]));
     });   
  };
};         

通過 promisify這個函數,就可以把接口進行轉換。

上面的模板就可以改成下面的形式:

1 var fs = require("fs");
2 var readFilePromise = promisify(fs.readFile, fs); //包裝為Promise接口
3 readFilePromise(filename, "binary").then(function(file){
4      //正常情況
5 }).catch(function(err){
6      //異常情況
7 })

特殊情況

有些設計不合理的接口可能會傳遞多個值給回調函數,如:

1 var fn = function(foo, callback){
2       if(success){
3             callback(null, file1, file2);
4       }else{
5             callback(err);
6       }
7 }

很明顯 這個接口傳了 file1,file2兩個值,是沒有辦法用上述方法的,用了上述接口轉換沒有辦法獲取到file2的數據。

對于這種情況只能手工包裝。

提高性能

可以使用高性能的Promise庫來提高性能。如:bluebird。簡單對比測試發現,blurbird 的性能是 V8 里內置的 Promise 3 倍左右.

替換內置的Promise:

  • global.Promise = require("bluebird");

如果項目里用了 Babel 編譯 ES6 代碼的話,可以用下面的方式替換:如果項目里用了 Babel 編譯 ES6 代碼的話,可以用下面的方式替換:

  • require("babel-runtime/core-js/promise").default = require("bluebird");
  • global.Promise = require("bluebird");

Babel 用于轉化你的 JavaScript 代碼 

你的 JavaScript 代碼是這樣的:

myJavaScript("foobar");

轉化之后的 JavaScript 是這樣的

myNewTransformedJavaScript("yay!");

 原文地址:http://welefen.com/post/how-to-convert-callback-to-promise.html


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()