Node中的util.promisify()方法的基本使用和實(shí)現(xiàn)
異步編程解決方案
我們知道,在JS
中實(shí)現(xiàn)異步編程主要是通過(guò)以下幾種方案:
- 回調(diào)函數(shù):也是在
ES6
之前用的最多的方式,缺點(diǎn)是容易造成callback hell
,可讀性很差 - 觀察者模式:在
NodeJS
中的很多模塊都繼承了EventEmitter
模塊,NodeJS
所有的異步I/O
操作在完成時(shí)都會(huì)發(fā)送一個(gè)事件到事件隊(duì)列。所有這些產(chǎn)生事件的對(duì)象都是events.EventEmitter
的實(shí)例。 Generator
:ES6 新引入了 Generator 函數(shù),可以通過(guò)yield
關(guān)鍵字,把函數(shù)的執(zhí)行流掛起,為改變執(zhí)行流程提供了可能,從而為異步編程提供解決方案。Promise
方案:號(hào)稱是異步編程的終極解決方案async / await
:async
是ES7引入的語(yǔ)法 ,也是屬于Promise
方案中的一種
今天就聊一下在node
中的一個(gè)util.promisify()
這個(gè)API
的基本使用和基本實(shí)現(xiàn)。
promisify
promisify
這個(gè)方法可以是一個(gè)高階函數(shù),接受一個(gè)函數(shù)作為入?yún)?,可以將原本考回調(diào)函數(shù)實(shí)現(xiàn)的異步編程轉(zhuǎn)化為promis
的方案。這也是node提供出來(lái),可以將之前非promise
的方法通過(guò)這個(gè)api
轉(zhuǎn)化成promise
來(lái)處理
基本使用
以一個(gè)簡(jiǎn)單的讀寫文件的fs.readFile
和readFileSync
為例說(shuō)明。我們知道fs.readFile
是通過(guò)回調(diào)函數(shù)的方式來(lái)獲取讀到的文件內(nèi)容。而fs.readFileSync
是通過(guò)同步的方式讀取到文件內(nèi)容。我們就可以使用promisify
這個(gè)函數(shù),將fs.readFile
轉(zhuǎn)變成promise
的方式
// const.js 被讀取的文件 const str = 123
// index.js const fs = require('fs') const path = require('path') const { promisify } = require('util') // 同步的方式讀取const.js const data = fs.readFileSync(path.resolve(__dirname, './const.js')) console.log('readFileSync:', data.toString()); // 通過(guò)回調(diào)函數(shù)的方式獲取const.js內(nèi)容 fs.readFile(path.resolve(__dirname, './const.js'), (error, data) => { if (error) console.log('error', error); console.log('readFile', data.toString()); }) // 將fs.readFile轉(zhuǎn)為promise的方式獲取文件內(nèi)容 const readFile = promisify(fs.readFile) readFile(path.resolve(__dirname, './const.js')) .then(data => { console.log('promisify: ', data.toString()) })
達(dá)到的效果也符合預(yù)期:
自己實(shí)現(xiàn)一個(gè)promisify
我們?cè)谶@里也自己實(shí)現(xiàn)一個(gè)promisify
函數(shù),達(dá)到上面的效果。即將一個(gè)接受回調(diào)函數(shù)通過(guò)回調(diào)完成異步編程的方式改為promise
的方式
我們分析分析,思路其實(shí)很簡(jiǎn)單, 原本的函數(shù)接受一系列的參數(shù),最后一個(gè)參數(shù)是一個(gè)回調(diào)函數(shù),一般在node
中錯(cuò)誤先行,最后一個(gè)參數(shù)即任務(wù)完成時(shí)的回調(diào)函數(shù)也接受兩個(gè)參數(shù)一個(gè)是error
一個(gè)是處理后得到最后結(jié)果的data
。如果有error
的話就reject
沒(méi)有就resolve
返回promise
結(jié)果即可,詳細(xì)分析步驟如下:
- 我們實(shí)現(xiàn)的
xpromisify
是一個(gè)高階函數(shù),即接受一個(gè)函數(shù)作為參數(shù) - 接受的這個(gè)函數(shù)也有可能接受參數(shù),所以我們對(duì)這個(gè)函數(shù)進(jìn)行升階處理,才能讓這個(gè)函數(shù)接受其他參數(shù)
- 我們最后返回的一定是一個(gè)
Promise
實(shí)例 - 我們可以將
步驟2
中這個(gè)函數(shù)接受的參數(shù)數(shù)組得到(比如上述例子中fs.readFile()
函數(shù)接受的path.resolve(__dirname, './const.js')
),再構(gòu)造一個(gè)函數(shù)作為回調(diào)函數(shù),作為完整的參數(shù),使用apply
的方式讓在步驟一
中接受的函數(shù)執(zhí)行 - 構(gòu)造的回調(diào)函數(shù)中判斷步函數(shù)完成是否有錯(cuò)誤,如果有錯(cuò)誤我們
reject
掉,如果沒(méi)有錯(cuò)誤的話就把這個(gè)data
給resolve
即可
完整的代碼實(shí)現(xiàn)如下所示:
// x-promisify.js // xPromisify 是一個(gè)高階函數(shù),會(huì)將接受的fn函數(shù)轉(zhuǎn)為promise const xPromisify = (fn) => { // 接受的fn函數(shù)也會(huì)接受其他參數(shù),所以升階處理,return 一個(gè)函數(shù)這樣就可以接受其他參數(shù)了 return wrapFn = (...args) => { // 最終返回的肯定是一個(gè)promise實(shí)例 return new Promise((resolve, reject) => { // 接受參數(shù)中加一個(gè)回調(diào)函數(shù)reject/resolve 最后結(jié)果 args.push((error, data) => { if (error) reject(error) resolve(data) }) // 此時(shí)args參數(shù)中就包含的fn執(zhí)行所需要的所有參數(shù)了 fn.apply(null, args) }) } } module.exports = { xPromisify }
我們可以通過(guò)上述例子的fs.readFile
這個(gè)函數(shù)來(lái)檢查一下:
const { xPromisify } = require('./x-promisify') const xReadFile = xPromisify(fs.readFile); xReadFile(path.resolve(__dirname, './const.js')) .then(data => { console.log('data', data.toString()) })
執(zhí)行效果如下所示:
總結(jié)
其實(shí)我們做的事情只是將回調(diào)函數(shù)的邏輯做了修改,原本是直接在回調(diào)中處理業(yè)務(wù)邏輯,這里我們修改為在回調(diào)函數(shù)中把異步事件處理的結(jié)果通過(guò)reject / resove
給返回出去 我們也可以看一下在NodeJS
中對(duì)這一部分的實(shí)現(xiàn):
到此這篇關(guān)于Node中的的util.promisify()方法的基本使用和實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Node 的util.promisify()方法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
koa-router路由參數(shù)和前端路由的結(jié)合詳解
這篇文章主要給大家介紹了關(guān)于koa-router路由參數(shù)和前端路由的結(jié)合的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用koa-router具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-05-05使用node.js實(shí)現(xiàn)微信小程序?qū)崟r(shí)聊天功能
在微信這個(gè)聊天工具里的小程序上實(shí)現(xiàn)聊天功能,總覺(jué)得很詫異,今天小編給大家?guī)?lái)了使用node.js實(shí)現(xiàn)微信小程序?qū)崟r(shí)聊天功能,感興趣的朋友一起看看吧2018-08-08nodejs如何在package.json中設(shè)置多條啟動(dòng)命令
這篇文章主要介紹了nodejs如何在package.json中設(shè)置多條啟動(dòng)命令,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03Node中的util.promisify()方法的基本使用和實(shí)現(xiàn)
眾所周知,在JS中實(shí)現(xiàn)異步編程主要是通過(guò)以下幾種方案,回調(diào)函數(shù),觀察者模式,Generator,Promise,async / await ,今天就和大家一起聊一下在node中的一個(gè)util.promisify()這個(gè)API的基本使用和基本實(shí)現(xiàn)2023-07-07Node.js 回調(diào)函數(shù)實(shí)例詳解
這篇文章主要介紹了Node.js 回調(diào)函數(shù)實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-07-07在Node.js中設(shè)置響應(yīng)的MIME類型的代碼詳解
在 Node.js 中設(shè)置響應(yīng)的 MIME 類型是為了讓瀏覽器正確解析服務(wù)器返回的內(nèi)容,比如 HTML、CSS、圖片、JSON 等,我們通常通過(guò)設(shè)置響應(yīng)頭中的 Content-Type 字段來(lái)完成,本文就給大家詳細(xì)介紹了在Node.js中設(shè)置響應(yīng)的MIME類型的方法,需要的朋友可以參考下2025-04-04