[譯] Node.js 8: util.promisify()

Nodejs 8 有一個新的工具函數 util.promisify()。他將一個接收回調函數參數的函數轉換成一個返回Promise的函數。html

一、util.promisify()小例子

若是你給如下命令傳入文件路徑,則會輸出文件內容node

// echo.js

const {promisify} = require('util');

const fs = require('fs');
const readFileAsync = promisify(fs.readFile); // (A)

const filePath = process.argv[2];

readFileAsync(filePath, {encoding: 'utf8'})
  .then((text) => {
      console.log('CONTENT:', text);
  })
  .catch((err) => {
      console.log('ERROR:', err);
  });

注意:在第一行,程序使用promisify()轉換基於回調函數的方法fs.readFile()成一個返回promise的一個函數git

下面的代碼片斷顯示這個腳本如何使用的github

$ node echo.js echo.js
CONTENT: const {promisify} = require('util');
···

$ node echo.js unknown.txt
ERROR: { Error: ENOENT: no such file or directory, ··· }

二、使用async函數

一樣的功能,可是經過async函數實現npm

// echoa.js

const {promisify} = require('util');

const fs = require('fs');
const readFileAsync = promisify(fs.readFile);

const filePath = process.argv[2];

async function main() {
    try {
        const text = await readFileAsync(filePath, {encoding: 'utf8'});
        console.log('CONTENT:', text);
    }
    catch (err) {
        console.log('ERROR:', err);
    }
}
main();

三、轉換有多個參數的回調函數爲Promise

下面的函數的回調函數接收多於一個的參數(除了error參數)數組

  • child_process.execpromise

  • child_process.execFileasync

  • dns.lookup函數

  • dns.lookupService工具

  • fs.read

  • fs.write

若是你轉換這些函數爲promise,它會返回一個對象(由多個參數組成的對象,而不是一個值)。例如,dns.lookup的回調函數包含下面幾個參數

  • err : Error

  • address : string

  • family : integer

轉換成Promise以後,它的參數將會變成{address, family}這樣一個對象

const util = require('util');
const dns = require('dns');
const lookupAsync = util.promisify(dns.lookup);

lookupAsync('nodejs.org')
    .then(obj => console.log(obj));
    // { address: '104.20.23.46', family: 4 }

promisify()經過內部符號internal/util/customPromisifyArgs處理非標準回調函數。所以不推薦傳入一個非標準的回調函數,也不該該去轉換咱們本身實現的回調(ps:本身就直接寫Promise就行了。。。)

四、定製的Promise函數

promisified的API來源於util.promisify.custom,它容許您將一個promisified版本附加到一個基於回調的函數。 在如下示例中,fooAsyncfoopromisified版本

const util = require('util');

function foo() {
    return 'abc';
}
async function fooAsync() {
    return 'abc';
}
foo[util.promisify.custom] = fooAsync;

console.log(util.promisify(foo) === fooAsync); // true

4.1 定製了promisified版本的標準函數

如今,有兩個標準函數有定製的promisified版本

> setImmediate[util.promisify.custom]
[Function]
> setTimeout[util.promisify.custom]
[Function]

五、低版本node兼容庫

Jordan Harband寫了一個庫a polyfill for util.promisify(),用來兼容promisify,使用方法以下

須要注意:

  1. js必須支持es5以上語法

  2. 必須支持Promise

  3. 待完善中

安裝

npm install util.promisify

使用方式有兩種

第一種,檢查是否有內置實現(Node 8)或者使用 polyfill (舊的Node版本)

const promisify = require('util.promisify');

const fs = require('fs');
const readFileAsync = promisify(fs.readFile);

第二種,在舊版本的Node上使用補丁模塊

const util = require('util');
require('util.promisify').shim();

const fs = require('fs');
const readFileAsync = util.promisify(fs.readFile);

翻譯自 Node.js 8: util.promisify()

相關文章
相關標籤/搜索