ESLint 报告了我认为没问题的代码的承诺滥用
Posted
技术标签:
【中文标题】ESLint 报告了我认为没问题的代码的承诺滥用【英文标题】:ESLint reports a promise misuse for code I consider ok 【发布时间】:2021-11-04 04:05:49 【问题描述】:在符号表实现中我有这个方法:
public getAllSymbols(type?: typeof Symbol, localOnly = false): Promise<Set<Symbol>>
const promise = super.getAllSymbols(type ?? Symbol, localOnly);
return new Promise(async (resolve, reject) =>
try
let result = await promise;
if (!localOnly)
this.dependencies.forEach(async (dependency) =>
result = new Set([...result, ...await dependency.getAllSymbols(type, localOnly)]);
);
resolve(result);
catch (reason)
reject(reason);
);
效果很好,但是 ESLint 报告了 2 个承诺滥用:
在函数参数中返回的 Promise 预期返回 void。
no-misused-promises
这段代码有什么问题,我必须如何编写它才能摆脱 linter 错误?
【问题讨论】:
可以想象问题在于执行器函数现在返回一个承诺(因为它被声明为异步),forEach 参数也是如此。这些函数都不应该返回任何东西。 我没有看到返回,除了函数返回的那个。看看eslint error description 就是我自己做的一个例子。 eslint错误描述告诉你,你的代码会报错——它是在错误代码的例子下。使函数异步自动将返回值包装在 Promise 中——即使你的函数中没有 return 语句——在这种情况下,它将返回 Promise代码中的问题:
Executor 函数不应该是 async
- 它是 anti-pattern
由于super.getAllSymbol(...)
已经返回了一个promise,所以不需要将它包装在promise 构造函数中——它是另一个anti-pattern。直接在super.getAllSymbol(...)
返回的promise上调用then()
方法
将async-await
与forEach()
一起使用不会给您预期的结果,因为forEach()
的回调函数不会等待等待的promise 解决——它只会继续下一次迭代。
您可以使用Promise.all()
和map()
方法来获得预期的输出。
您也可以使用for-of
循环,但如果您不希望所有承诺都以顺序方式解决,则使用Promise.all()
会更好。
您的代码可以重写为(为简单起见删除类型):
public getAllSymbols(type, localOnly = false)
const promise = super.getAllSymbols(type ?? Symbol, localOnly);
return promise
.then(result =>
if (!localOnly)
return Promise.all(this.dependencies.map(dep => (
dep.getAllSymbols(type, localOnly))
)))
.then(resultArr =>
return new Set([...result, ...resultArr]);
);
else
return result;
);
或者您可以使用async-await
语法:
public async getAllSymbols(type, localOnly = false)
const result = await super.getAllSymbols(type ?? Symbol, localOnly);
if (!localOnly)
const resultArr = await Promise.all(this.dependencies.map(dep => (
dep.getAllSymbols(type, localOnly)
)));
return new Set([...result, ...resultArr]);
return result;
我删除了catch
块,因为在我看来,调用代码应该处理错误(如果有的话)。
上面的函数可以调用为:
getAllSymbols(...)
.then(result => ... )
.catch(error => ... );
或者你可以使用async-await
语法:
try
const result = await getAllSymbols(...);
...
catch (error)
// handle error
【讨论】:
注意:您可能需要修复集合合并的代码。resultArr
不是符号数组,而是符号集数组。所以你需要在数组上循环来构造最终的集合。以上是关于ESLint 报告了我认为没问题的代码的承诺滥用的主要内容,如果未能解决你的问题,请参考以下文章
ESLint 可以帮助你防止 Unhandled-Promise-Rejections 吗?
使用 ESLint `indent` 规则忽略模板文字中的缩进