50

Promise 化回调式函数

 5 years ago
source link: https://csspod.com/promisify-function/?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Node.js 8 提供了新的工具函数: util.promisify ,用于把形如 (err, value) => ... 的回调式函数转换为 Promise 版本。

基本使用

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);

stat('.').then((stats) => {
  // Do something with `stats`
}).catch((error) => {
  // Handle the error.
});

当然,也可以使用 Node 8 另一个新功能 async function 调用:

const util = require('util');
const fs = require('fs');

const stat = util.promisify(fs.stat);

async function callStat() {
  const stats = await stat('.');
  console.log(`This directory is owned by ${stats.uid}`);
}

自定义函数的 Promise 版本

通过设置 util.promisify.custom symbol,可以自定义 util.promisify() 的返回值:

const util = require('util');

function doSomething(foo, callback) {
  // ...
}

doSomething[util.promisify.custom] = (foo) => {
  return getPromiseSomehow();
};

const promisified = util.promisify(doSomething);

console.log(promisified === doSomething[util.promisify.custom]);
// prints 'true'

自定义 Promise symbol 一般用于源函数不遵循 (err, value) => ... 回调的场景,比如 (foo, onSuccessCallback, onErrorCallback) 式回调的函数:

doSomething[util.promisify.custom] = (foo) => {
  return new Promise((resolve, reject) => {
    doSomething(foo, resolve, reject);
  });
};

回调函数中包含超过两个参数的函数

诸如以下函数,回调中除了 err 参数,还包含多个参数:

  • child_process.exec
  • child_process.execFile
  • dns.lookup
  • dns.lookupService
  • fs.read
  • fs.write

经过 util.promisify 处理的 Promise 版本会将多个参数组装成对象返回。

例如, dns.lookup() 的回调有三个参数:

  • err: Error
  • address: 字符串
  • family: 整数

Promise 化后,返回 {address: '', family: 3} 这样的对象:

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 }

老版本 Node

Polyfill: util.promisify 模块

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

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

pify

pify 是一个小而美的 Promise 化工具,处理了一些有用的细节,如自动 this 绑定,这是内置的 util.promisify 中没有的。

const fs = require('fs');
const pify = require('pify');

// Promisify a single function
pify(fs.readFile)('package.json', 'utf8').then(data => {
  console.log(JSON.parse(data).name);
  //=> 'pify'
});

// Promisify all methods in a module
pify(fs).readFile('package.json', 'utf8').then(data => {
  console.log(JSON.parse(data).name);
  //=> 'pify'
});

参考链接


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK