摘要:今天要介紹的是,就是回調函數與間的橋梁。什么樣的叫有兩個條件回調函數在主函數中的參數位置必須是最后一個回調函數參數中的第一個參數必須是。
作者:晃晃
本文原創,轉載請注明作者及出處
Promise 自問世以來,得到了大量的應用,簡直是 javascript 中的神器。它很好地解決了異步方法的回調地獄、提供了我們在異步方法中使用 return 的能力,并將 callback 的調用納入了自己的管理,而不是交給異步函數后我們就無能為力了(經常有 callback 被莫名調用兩次而導致程序出錯)。
今天要介紹的是 Promisify,就是回調函數與 Promise 間的橋梁。
1. promisify 介紹什么是 promisify 呢?顧名思義,就是“promise 化”,將一個不是promise的方法變成 promise 。舉個例子:
// 原有的callback調用 fs.readFile("test.js", function(err, data) { if (!err) { console.log(data); } else { console.log(err); } }); // promisify后 var readFileAsync = promisify(fs.readFile); readFileAsync("test.js").then(data => { console.log(data); }, err => { console.log(err); });
這兩個方法效果上是等價的,但是從掌控性來說的話,我更喜歡后面的寫法。
那么什么樣的方法可以通過 promisify 變成 promise 呢?這里就需要介紹一個名詞,nodeCallback。什么樣的 callback 叫 nodeCallback ?
nodeCallback 有兩個條件:1. 回調函數在主函數中的參數位置必須是最后一個;2. 回調函數參數中的第一個參數必須是 error 。舉個例子:
回調函數在主函數中的參數位置
// 正確 function main(a, b, c, callback) { } // 錯誤 function main(callback, a, b, c) { }
回調函數參數中的第一個參數必須是 error
// 正確 function callback(error, result1, result2) { } // 錯誤 function callback(result1, result2, error) { }
這樣,通過 nodeCallback ,我們定義了一個能被 promisify 的函數的格式,即,滿足 nodeCallback 形式的方法,我們可以通過 promisify 來讓它變成一個返回 promise 的方法。
2. promisify 的實現下面我們來根據上述條件來手動實現一個 promisify 。
首先 promisify 需要返回一個 function ,并且這個 function 要返回一個 promise
var promisify = (func) => { return function() { var ctx = this; return new Promise(resolve => { return func.call(ctx, ...arguments); }) } }
其次,原 func 的最后一個參數是 callback
var promisify = (func) => { return function() { var ctx = this; return new Promise(resolve => { return func.call(ctx, ...arguments, function() { resolve(arguments); }); }) } }
然后,回調函數中的第一個參數是 error 標記
var promisify = (func) => { return function() { var ctx = this; return new Promise((resolve, reject) => { return func.call(ctx, ...arguments, function() { var args = Array.prototype.map.call(arguments, item => item); var err = args.shift(); if (err) { reject(err); } else { resolve(args); } }); }) } }
最后,做一些優化,比如 this 作用域的自定義、回參只有一個時不返回數組
var promisify = (func, ctx) => { // 返回一個新的function return function() { // 初始化this作用域 var ctx = ctx || this; // 新方法返回的promise return new Promise((resolve, reject) => { // 調用原來的非promise方法func,綁定作用域,傳參,以及callback(callback為func的最后一個參數) func.call(ctx, ...arguments, function() { // 將回調函數中的的第一個參數error多帶帶取出 var args = Array.prototype.map.call(arguments, item => item); var err = args.shift(); // 判斷是否有error if (err) { reject(err) } else { // 沒有error則將后續參數resolve出來 args = args.length > 1 ? args : args[0]; resolve(args); } }); }) }; };
測試
// nodeCallback方法func1 var func1 = function(a, b, c, callback) { callback(null, a+b+c); } // promise化后的func2 var func2 = promisify(func1); // 調用后輸出6 func1(1, 2, 3, (err, reuslt) => { if (!err) { console.log(result); //輸出6 } }) func2(1, 2, 3).then(console.log); //輸出6
以上便是 promisify 的介紹和實現,事實上有很多用 callback 來實現異步的第三方庫提供的方法都是按照 nodeCallback 格式的,所以它們都可以通過 promisify 來讓它變成 promise ,在遇到這些方法的時候就可以更靈活地使用啦。
iKcamp官網:http://www.ikcamp.com
訪問官網更快閱讀全部免費分享課程:《iKcamp出品|全網最新|微信小程序|基于最新版1.0開發者工具之初中級培訓教程分享》。
包含:文章、視頻、源代碼
【11月11號】上海iKcamp最新活動iKcamp原創新書《移動Web前端高效開發實戰》已在亞馬遜、京東、當當開售。
報名地址:http://www.huodongxing.com/ev...
與“天天練口語”小程序總榜排名第四、教育類排名第一的研發團隊,面對面溝通交流。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89433.html
摘要:自定義的化有那么一些場景,是不能夠直接使用來進行轉換的,有大概這么兩種情況沒有遵循約定的回調函數返回多個參數的回調函數首先是第一個,如果沒有遵循我們的約定,很可能導致的誤判,得不到正確的反饋。 util.promisify是在node.js 8.x版本中新增的一個工具,用于將老式的Error first callback轉換為Promise對象,讓老項目改造變得更為輕松。 在官方推...
摘要:參考文檔升級后的函數回調參數問題中的使用方法和還是不一樣的源碼講解的內部機制優化相關內容文章官方文檔簡述使用過的都知道這個方法的作用,通過該方法會讓形式的函數風格轉換成方法,可以認為是一顆語法糖,例如接下來我們就分析一下這個的內部流程。 參考文檔 升級bluebird 3后Promise.promisify的函數回調參數問題:3中的使用方法和2還是不一樣的 How does Bl...
摘要:初學,用開發項目。而且還是個不小的項目,說起來挺冒險的。一開始比較簡單,并沒有使用也能順利進行,隨著開發的深入,到了不用不行的地步了。于是產生了一個問題,一些之前寫的方法并不支持,如果直接改成,那之前調用過的地方也都得改,工作量有點大。 初學 Node.js,用 Express 開發 Web 項目。而且還是個不小的項目,說起來挺冒險的。 一開始比較簡單,并沒有使用 Promise 也能...
摘要:今天碰到一個需要用做無窮循環的一個案例,頓時腦洞大開。事情是這樣的,有這樣的一群異步函數,將它們封裝成,依次放入一個數組內需要讓數組里的每一個依次進行,最后一個執行完就結束。 今天碰到一個需要用Promise做無窮循環then的一個案例,頓時腦洞大開。事情是這樣的,有這樣的一群異步函數, var func1 = function(callback){ setTimeout(fu...
摘要:而適配器其實在中應該是比較常見的一種了。在維基百科中,關于適配器模式的定義為在軟件工程中,適配器模式是一種軟件設計模式,允許從另一個接口使用現有類的接口。 適配器設計模式在JavaScript中非常有用,在處理跨瀏覽器兼容問題、整合多個第三方SDK的調用,都可以看到它的身影。 其實在日常開發中,很多時候會不經意間寫出符合某種設計模式的代碼,畢竟設計模式就是老前輩們總結提煉出來的一些能...
閱讀 3101·2021-09-22 15:54
閱讀 3989·2021-09-09 11:34
閱讀 1773·2019-08-30 12:48
閱讀 1164·2019-08-30 11:18
閱讀 3437·2019-08-26 11:48
閱讀 921·2019-08-23 17:50
閱讀 2123·2019-08-23 17:17
閱讀 1246·2019-08-23 17:12