1. 场景
- 原生回调函数 callBack:存在回调地狱问题
- 函数加上返回 Promise 对象构造成异步函数:每次都需要重新构造,重复工作
- 使用
Promisify
做 Promise 的封装:减少构造 Promise 的重复工作
2. 实现
function promisify(original){
function fn(...args){
return new Promise((resolve, reject) => {
args.push((err, ...values) => {
if(err){
return reject(err);
}
resolve(values);
});
Reflect.apply(original, this, args);
});
}
return fn;
}
3. 使用
function loadImage() { ... }
const loadImagePromise = promisify(loadImage);
async function load(){
try{
const res = await loadImagePromise(imageSrc);
console.log(res);
}
catch(err){
console.log(err);
}
}
load();
4. 源码解析
4.1 返回 reject 和 resolve 的依据?
promisify 源码 4~9 行
在 Node 中,回调的第一个参数永远是 Error 对象,其余的参数才是正确的数据;
因此可以判断,第一个参数有值的情况下,触发 reject;其余情况触发 resolve。
args.push((err, ...values) => {
if(err){
return reject(err);
}
resolve(values);
});
4.2 Reflect 是什么?使用场景?
阮一峰 ES6
1)是什么?
- 基于反射机制:程序在运行时能获取到自身的信息
- Reflect 不是构造器,内部的属性和方法都是静态的
- 为某些操作做 简化,比如
for...in / Object.keys()
等
2)使用场景?
遍历带有 Symbol 的对象
var s = Symbol('foo');
var k = 'bar';
var o = { [s]: 1, [k]: 1 };
// getOwnPropertyNames获取到String类型的key,getOwnPropertySymbols获取到Symbol类型的key
// 不使用 Reflect
var keys = Object.getOwnPropertyNames(o).concat(Object.getOwnPropertySymbols(o));
// 使用 Reflect
Reflect.ownKeys(o)
3)Reflect.apply 与 Function.apply 的区别
Reflect.apply
:Reflect.apply ( target, thisArgument , [argumentsList] )Function.apply
:Function.apply ( thisArgument , [argumentsList] )
// Function.apply:
var youngest = Math.min.apply(Math, ages);
var oldest = Math.max.apply(Math, ages);
var type = Object.prototype.toString.call(youngest);
// Reflect.apply:
var youngest = Reflect.apply(Math.min, Math, ages);
var oldest = Reflect.apply(Math.max, Math, ages);
var type = Reflect.apply(Object.prototype.toString, youngest, []);