javascript - 传递和调用函数的正确方法
在 Node 中使用外部 SDK 时,我注意到我写了很多重复的代码。例如:
async function one(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.one(function(err, req, res) {
if (err) {
return reject(err);
}
resolve(res);
});
});
}
async function two(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.two(function(err, req, res) {
if (err) {
console.log(err);
return reject(err);
}
resolve(res);
});
});
}
我想简化和抽象它,使其更清晰,然后想到了这个:
async function runner(fn, params?): Promise<any> {
return new Promise(function(resolve, reject) {
const _CB = cb.bind({ resolve, reject });
if (params) {
return fn(params, _CB);
}
return fn(_CB);
});
}
const one = async (): Promise<any> => {
return runner(sdk.one);
};
const two = async (): Promise<any> => {
return runner(sdk.two);
};
不过,当我运行这个时会遇到错误,即 this.helper is not a function。我认为问题在于 Javascript 是按值传递的。因此,当我在 runner 内运行 fn(_CB) 并尝试引用其父级的一个函数 this.helper 时,它不知道 this 是什么,因为 fn 只是一个复制出来的代码块。实际上,在我想到这个之前,我尝试过对 sdk 函数使用 util.Promisify,但仍然出现和这里一样的错误。
我想到了这个变通办法,但我想知道是否有更好的方法?
async function runner(fn, params?): Promise<any> {
return new Promise(function(resolve, reject) {
const _CB = cb.bind({ resolve, reject });
if (params) {
return fn(params, _CB);
}
return fn(_CB);
});
}
const one = async (): Promise<any> => {
return runner((x) => sdk.one(x));
};
答案#1
当 SDK 尝试回调你时,你的作用域丢失了吗?你可以使用箭头函数在这些调用中保留作用域。它的工作方式类似于你为较旧目标使用的中间 _CB 变量,但在更新的 ECMAScript 版本中,它是原生支持的。
async function one(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.one((err, req, res) => { // Scope preserving arrow function
if (err) {
return reject(err);
}
resolve(res);
});
});
}
async function two(): Promise<any> {
return new Promise((resolve, reject) => {
sdk.two((err, req, res) => { // and here
if (err) {
console.log(err);
return reject(err);
}
resolve(res);
});
});
}
答案#2
嗯,你在使用 JavaScript,这种语言几乎允许你做任何事情。你可以动态调用函数
async function promisify(fnName): Promise<any> {
return new Promise((resolve, reject) => {
sdk[fnName](function(err, req, res) {
if (err) {
return reject(err);
}
resolve(res);
});
});
}
并将其称为 promisify('one')
如果你正在使用当前的 LTS 8.X Node 版本或更高版本,你可以使用 https://nodejs.org/dist/latest-v8.x/docs/api/util.html#util_util_promisify_original
如果不行,你可以尝试使用蓝鸟方法来处理:http://bluebirdjs.com/docs/api/promise.promisify.html
