【问题标题】:ESLint reports a promise misuse for code I consider okESLint 报告了我认为没问题的代码的承诺滥用
【发布时间】: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......你总是可以等待异步函数。跨度>

标签: javascript eslint


【解决方案1】:

代码中的问题:

  • Executor 函数不应该是 async - 它是 anti-pattern

  • 由于super.getAllSymbol(...) 已经返回了一个promise,所以不需要将它包装在promise 构造函数中——它是另一个anti-pattern。直接在super.getAllSymbol(...)返回的promise上调用then()方法

  • async-awaitforEach() 一起使用不会给您预期的结果,因为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 不是符号数组,而是符号集数组。所以你需要在数组上循环来构造最终的集合。
猜你喜欢
  • 1970-01-01
  • 2019-08-29
  • 2017-05-17
  • 2023-03-26
  • 1970-01-01
  • 1970-01-01
  • 2019-10-11
  • 2018-01-16
  • 2017-06-19
相关资源
最近更新 更多