TIP
将原本需要通过传入回调参数来实现回调执行(或者叫同步执行)改为利用promise的.then的方式来调用,从而实现逻辑上的同步操作。
# 异步函数promise化
// 第一种
module.exports = function promisify(fn) {
return function (...args) {
return new Promise(function (resolve,reject) {
// args.push(function (err,...arg) {
// if(err){
// reject(err)
// }else{
// resolve(...arg);
// }
// });
args.push(function (...arg) {
resolve([...arg]);
});
fn.apply(null, args);
})
}
}
// 第二种
module.exports = function promisify(fn) {
return function(...args) {
return new Promise((resolve, reject) => {
let callback = function(...args) {
resolve(args); // 注意不能用...运算符 只能传入一个参数
}
fn.apply(null, [...args, callback]);
})
}
}
# 实例
# 例子1
// foo 可以是任何需要调用回调函数的函数
function foo(str1, str2, callback) {
setTimeout(() => {
console.log('setTimeout');
// callback函数是通过最后一个参数这个位置来识别的,与callback名字无关
callback(str1, str2)
}, 1000);
}
// 这里的agent已经不是foo函数,而是我们在promisify中返回的自定义匿名函数
// 所以不需要纠结是否传入callback函数。
let agent = promisify(foo);
agent('hello', 'world').then(res => {
console.log(res);
})
输出结果:
setTimeout
[ 'hello', 'world' ]
# 例子2
function fun(arg, callback) {
try {
// aaa()
callback(null, 'result')
} catch (error) {
callback(error)
}
console.log('fs ' + arg)
}
const promise = promisify(fun)
// await方式
setTimeout(async () => {
try {
await promise('./aaa.txt', (err, data) => {
console.log(err ? 'read err' : `${data}1`);
})
} catch (error) {
console.log('catch err', error)
}
})