【手写 Promise 源码】第十四篇 - 实现工具方法 promisify

638 阅读2分钟

一,前言

上一篇,实现了 Promise 的两个静态 API:Promise.allSettledPromise.any,主要涉及以下几个点:

  • 测试原生 Promise.allSettled 的使用;
  • Promise.allSettled 的功能与特性分析;
  • Promise.allSettled 的源码实现、执行分析、功能测试;
  • 测试原生 Promise.any 的使用;
  • Promise.any 的功能与特性分析;
  • Promise.any 的源码实现、执行分析、功能测试;

本篇,实现一个 promisify 功能的工具函数;


二,promisify 介绍

1,什么是 promisify

promisify功能:如字面意思“promise 化”

用于将异步回调 callback 形式的操作或 API 转换为 promise 形式;

2,promisify 的应用场景

目前主要用于 nodejs、小程序等场景

这些框架提供的 API 多为异步回调方式,比较容易形成编码中的“回调地狱”问题;

示例:nodejs 异步读取文件

const fs = require('fs') // 文件操作
fs.readFile('test', 'utf8', function(err, data){
  if(err) reject(err) // 错误优先原则
  fs.readFile(data, 'utf8', function(err, data){
   if(err) reject(err)
   console.log(data);
   // ...
  })
})

在 nodejs 提供的 util 工具包中也存在一个 promisify 函数:

const fs = require('fs')
const util = require('util')
// 将原本 callback 形式的异步API readFile -> promise 化
let readFile = util.promisify(fs.readFile);
readFile('test', 'utf8').then((data)=>{
  return readFile(data, 'utf8');
}).then((data)=>{
  console.log(data);
}).catch(err =>{// ...})

还提供了批量 promisify 操作:

let fs = require('fs');
promisifyAll(fs); // 对 fs 库导出的对象整体 promisify;

fs.readFileAsync('test', 'utf8').then(data=>{
  console.log(data);
});

备注:promisifyAll 对库导出的对象整体 promisify 操作后,新的方法命名规则一般为:原方法名+"Async"

避免了异步回调导致的多层嵌套问题,提升了代码的可读性;

下面就一起实现一个 promisify;


三,promisify 实现

  • 实现单一函数的 promise 化:
function promisify(fn) {
  return function (...args) {
    return new Promise((resolve, reject) => {
      fn(...args, (err, data) => {
        if (err) reject(err);
        resolve(data);
      })
    })
  }
}

这样,fn 就被进行了一次包装:将 callback 回调方式转为 promise 形式;

  • 批量 promise 化:
function promisifyAll(obj) {
  // 将对象转为数组,遍历数组中的fn,依次完成 promisify 操作
  Object.keys(obj).forEach(key => {
    if (typeof obj[key] === 'function') {
      obj[key + 'Async'] = promisify(obj[key])
    }
  })
}

备注:目前很多框架和库的 API 都有对 promise 的支持,所以使用时可以查阅文档,如果实在没有,可以使用以上 promisify 函数进行转化;如:可以使用 bluebird.js


四,结尾

本篇,实现一个 promisify 工具函数,主要涉及以下几个点:

  • promisify 简介和测试;
  • promisify 功能的实现:promisify、promisifyAll;

下一篇,介绍 generator 生成器;