我正在参与掘金会员专属活动-源码共读第一期,点击参与
普通转化 callback
callback 回调地狱,应该很多人都有经历过。应该有很多项目都会以 callback 的方式实现异步的过程。但我们肯定会遇到这样的场景:使用某个类库时发现提供的还是 callback 方式,而你项目早就迭代优化为 promise 或者是 async/await 的方式。
所以,promisify 函数就有其存在意义。其能够把 callback 形式转成 promise 形式。在之前,可能都会像我一样自己手动实现将 callback 转成 promise。
function convertPromise(id) {
return new Promise((resolve,reject)=>{
getUser(id,(err, result)=>{
if(err) { reject(err)}
resolve(err)
})
})
}
function getUser(id, function(err, result){
if (err){return;}
console.log(true)
})
promisify 转化 callback
promisify 就是实现了支持所有 callback 形式的转化,封装了一个通用的函数,使用简单方便。简单一行代码实现了上面8行代码的功能。
const getUserPromise = promisify(getUser);
const result = await getUserPromise(id);
源码分析
function promisify(original){
function fn(...args){
return new Promise((resolve, reject) => {
args.push((err, ...values) => {
if(err){
return reject(err);
}
resolve(values);
});
// original.apply(this, args);
Reflect.apply(original, this, args);
});
}
return fn;
}
从上面的源码可以看到 promisify 函数详细实现的过程:
- 参数是原函数,返回结果时一个封装后的函数。所以在使用 promisify 函数后返回得到的是一个新的函数。
- 新函数 fn 返回结果就是个 promise 。调用它时参数就是原函数的参数,并在原参数后增加了一个回调函数
- 回调函数的第一个参数是 err 错误信息,第二个是 promise 返回值
Reflect.apply
其中 Reflect.apply(original, this, args) 它是什么?
MDN 上的解释是:静态方法 Reflect.apply() 通过指定的参数列表发起对目标(target)函数的调用。
Reflect . apply ****接收三个参数:
- target :要调用的目标函数
- thisArgument:target函数调用时绑定的this对象
- ArgumentsList ****:它是一个类似数组的对象,用于指定应调用目标的参数。
返回值是目标函数的执行结果。
所以,Reflect.apply 其实就是一个函数的绑定并执行函数的过程,操作就和 Function.prototype.apply.call(func, thisArg, args)一样的。