node中promiseify详解(注意this指向)

85 阅读1分钟

express里面有个util模块,这个模块主要的功能是将callback形式的异步api转换成promise形式的.
作用:原本需要通过传入回调函数来实现,但是现在可以用promise.then的方式来调用

promisify是个函数,参数也是函数,返回值也是函数

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

const reader = promisify(fs.readFile)

reader('./ww.txt', { encoding: 'utf-8' }).then((res) => {
  console.log(res)
}).catch((err) => {
  console.log(err)
})

内部实现方式

const promisify = (fn) => {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn(...args, (err, data) => {
        if (err) reject(err)
        resolve(data)
      })
    })
  }
}

const demo = promisify((a, b, c, cb) => {
  console.log(a, b, c)
  cb(null, a)
})

demo(1, 2, 3).then((res) => {
  console.log(res, 'res')
})

这是一个高阶函数柯里化,首先解释一下,因为在node中异步回调有一个约定:Error first , 也就是回调函数中的第一个参数一定要是Error对象,其余参数才是正确的数据,所以实现起来很简单,在匹配到第一个参数有值,也就是有error的话触发reject否则触发resolve

  1. promisify返回一个匿名函数,匿名函数接受原函数的参数
  2. 匿名函数被调用后根据这些参数来调用真实的函数,同时拼接一个用来处理结果的回调函数callback
  3. 监测到err有值,触发reject,其他情况触发resolve

注意:resolve只能传入一个参数,所以callback中没有必要使用...arg获取所有返回值
...args只是为了将参数类数组转换成真正的数组
如果赋值给其他变量,那么this指向可能会出问题,所以一般使用箭头函数,或者bind绑定对应的 this