JavaScript Promises 混淆反模式?

7

我花了一整天的时间试图弄清楚我是否错误地使用了Promise。

这是反模式吗?

export const myExample = (payload) => {
  return new Promise((resolve, reject) => {})
}

我可以用异步代码在 Promise 中使用吗?
export const myExample = (payload) => {
  return new Promise(async (resolve, reject) => {})
}

那么这是错的吗?假设添加async默认会将其变成promise。

export const myExample = async (payload) => {
  return new Promise((resolve, reject) => {})
}

如果是这种情况,那我是否应该从函数中返回,这样就相当于resolve;如果我抛出错误,那么就是reject。这样看起来是这样的吗?

export const myExample = async (payload) => {
  if(payload) return true
  else throw new Error('Promise rejection?')
}

那么“first”和“last”是一样的吗?

1
new Promise(async (resolve, reject) 总是被认为是一种“代码异味”... - Jaromanda X
在定义 Promise 时,不应该使用 async await,这些关键字只应该在执行 Promise 时使用。如果你在定义 Promise 时使用它们,会让人不清楚你想要做什么以及你的问题是什么。 - EugenSunic
这本身并不是问题,我在为我的应用程序制作自己的承诺。但是在这些承诺中,我想使用数据库调用或fs异步调用,例如await fs.writeFile()。所以您的意思是我不应该在Promise内部使用await?所以只需使用fs.writeFile().then().catch() - uneasy
第二个和第三个可以写成 async (payload) => {},不确定在微任务世界中是否会有一些差异... async await 使用 try catch finally,还有 fs.promises ;) - Estradiaz
永远不要将async function作为执行器传递给new Promise(https://dev59.com/8lgQ5IYBdhLWcg3wRBzK),其他情况大多都没问题。(你可能并不是真的在构造一个永远不会解决的`new Promise`,而是在其中做了一些事情,对吧?) - Bergi
4个回答

3
export const myExample = (payload) => {
  return new Promise((resolve, reject) => {})
}

这个方法仅应该用于将不是基于 Promise 但返回异步结果的代码转换为 Promise。

export const myExample = (payload) => {
  return new Promise(async (resolve, reject) => {})
}

异步反模式是指在使用async时,函数本身就返回一个Promise,但是在此处打断了Promise链。

export const myExample = async (payload) => {
  return new Promise((resolve, reject) => {})
}

与第一个示例相同,new Promise 应仅用于将非 Promise-based 但异步返回结果的代码转换为 Promise。是否可以使用 async 取决于该函数中的其他代码。但最好的方法是如果您需要使用 new Promise((resolve, reject) => {}),则封闭函数仅包含并返回那个 new Promise,就像在您的第一个示例中一样。

那么如果是这种情况,我是否应该从函数中返回结果,这将和 resolve 相同,如果出错会抛出错误,这将和 reject 相同,所以看起来是这样的?

是的


谢谢,我现在明白了。嗯,我之前用错了。所以我的结论是,在我的情况下,大多数时候,我只想在自己的 Promise 中包装其他的 await 调用。所以对我来说最好的方式就是 export const myExample = async (payload) =>{} 并进行我的异步调用,然后如果解决了就返回任何东西,如果没有解决就抛出错误? - uneasy
1
所以对我来说最好的方法就是只导出 const myExample = async (payload) => {} 并进行我的异步调用,然后如果解决了问题就返回任何东西,如果没有解决问题就抛出错误。是的,如果你的意思是这样的:const myExample = async (payload) =>{ let res = await someTask(); if( res == "unexpected value") { throw new Error("something went wrong") } return res; },如果你调用 myExample,它将返回一个 Promise,该 Promise 要么被解析为 res,要么被拒绝并带有该错误。 - t.niese

2

这是一个好问题,我也遇到了类似的困惑,想知道在哪里以及使用什么样的结构。我得出了这个结果:

async/await - 我在高层次上使用它,大多数情况下我编写我的处理部分

async function asyncExample() {
  try {
    const sampleData = await otherFunction();
    // You code here
  } catch (err) {
    // Your error handling here
  }
}

async/await中使用try/catch是一个好主意。

使用new Promise(resolve, reject)的概念。当我需要封装仅支持回调函数的函数时,我通常会使用它。

function promiseExample() {
  return new Promise((resolve, reject) => {
    // your code to resolve()
    // otherwise to reject()
  });
}

但是有一个很好的模块promisify,有时比包装每个函数更好。


0
这不是反模式,你需要在promise内部的resolve函数中对payload参数进行一些逻辑处理,例如resolve(payload+'连接'),同时你应该根据payload参数来实现reject函数。
 export const myExample = (payload) => {
      return new Promise((resolve, reject) => {})
    }

在定义一个 Promise 之后,不应该使用 async await,这些关键字只能在调用/执行 Promise 时使用。

export const myExample = (payload) => {
  return new Promise(async (resolve, reject) => {})
}

同样适用于此代码片段。
export const myExample = async (payload) => {
  return new Promise((resolve, reject) => {})
}

由于您使用了async关键字,因此应在函数内部使用await。此外,在代码片段中未定义任何承诺,因此请确保在使用async await之前定义它们,这样您就可以返回一些值或引发错误。

export const myExample = async (payload) => {
  if(payload) return true
  else throw new Error('Promise rejection?')
}

-1

这被认为是一种“反模式”,因为存在错误未被捕获的可能性。如果async函数中的执行引发错误,该错误将丢失,并且不会导致新构造的Promise拒绝。

您可以通过确保使用try/catch来解决此问题,尽管这种必要要求可能会使您的代码更脆弱。

我如何正确使用这个模式?

function promise() {
    return new Promise(async (resolve, reject) => {
        try {
            await iWillThrow() // throw err
        } catch (error) {
            reject(error) // need to reject here, error will not 'bubble'
        }
    });
}

这个模式会如何使我失误?

function promise() {
    return new Promise(async (resolve, reject) => {
            await iWillThrow() // throw err, unhandled error ⚠
    });
}

我发现这里的 ESLint 解释很有用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接