【问题标题】:JavaScript Promises confusion anti-pattern?JavaScript Promises 混淆反模式?
【发布时间】:2020-12-04 03:39:39
【问题描述】:

我花了一整天的时间来弄清楚我错误地使用了 Promises 的天气。

这是反模式吗?

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) => {})
}

如果是这种情况,我是否应该从与解析相同的函数返回,如果我抛出错误将被拒绝,所以看起来像这样?

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

那么 first 和 last 是一样的吗?

【问题讨论】:

  • new Promise(async (resolve, reject) 总是“代码味道”...
  • 你不应该在定义 Promise 时使用 async await,这些应该只在执行 Promise 时使用,不清楚你想做什么以及你的问题是什么
  • 这不是问题,我正在为我的应用做出自己的承诺。但在这些承诺中,我想使用数据库调用或 fs 异步调用,例如等待fs.writeFile() 所以你是说我不应该在 Promise 里面有await ?所以只需使用 fs.writeFile().then().catch() ?
  • 第二个和第三个可以写成async (payload) => {},不知道微任务世界会不会有一些不同,... async await 使用 try catch finally,也是 fs.promises ;)跨度>
  • Never pass an async function as the executor to new Promise,其他都还好。 (你可能并没有真正构建一个永远不会解析的new Promise,你实际上在里面做了一些事情,对吧?)

标签: javascript promise


【解决方案1】:

这是一个很好的问题,我也面临着这种困惑,想知道在哪里使用什么样的结构。想出了这个:

async/await - 我在高级别的地方使用它,主要是我编写处理部分

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

async/await

中使用 try/catch 总是一个好主意

使用新的 Promise(resolve, reject) 概念。当我必须包装一个只支持回调的函数时,我主要使用它。

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

但是有一个不错的模块 promisify 有时是一个比包装每个函数更好的解决方案

【讨论】:

    【解决方案2】:
    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 但异步返回结果的代码转换为 Promise。是否可以提交 async 取决于该函数中的其他代码。但是,如果您需要使用 new Promise((resolve, reject) => {}) 封闭函数只包含并返回 new Promise 就像在您的第一个示例中一样,这会更好。

    如果是这种情况,我是否应该从与解析相同的函数返回,如果我抛出错误将被拒绝,所以看起来像这样?

    是的

    【讨论】:

    • 谢谢,我想我现在明白了。好吧,我用错了。因此,作为我的结论,在大多数情况下,我只想将其他等待调用包装在我自己的承诺中。所以对我来说最好的就是export const myExample = async (payload) =>{} 并进行 mu 异步调用,然后如果解决则返回任何内容,如果不解决则抛出错误?
    • So the best for me would be just export const myExample = async (payload) =>{} and doing mu async calls, then return whatever if resolve and throw error if doesn't resolve 是的,如果你的意思是这样的:const myExample = async (payload) =>{ let res = await someTask(); if( res == "unexpected value") { throw new Error("something went wrong") } return res; },如果你调用myExample,它将返回一个被解析为res 或被拒绝并出现该错误的 Promise .
    【解决方案3】:

    这不是一个反模式,你需要使用 resolve 函数对你的有效载荷参数做一些逻辑,例如 resolve(payload+'concatenate') ,你也应该根据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) => {})
    }
    

    这段代码sn-p也是如此

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

    你应该在你的函数中使用 await,因为你使用的是 async 关键字,而且在 sn-p 中也没有定义 promise,所以请确保在使用 async await 之前定义它们,因此你将能够返回一些值或者抛出错误

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

    【讨论】:

      【解决方案4】:

      这被认为是一种“反模式”,因为存在错误可能未被发现的可能性。如果 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 解释 here 很有用。

      【讨论】:

        猜你喜欢
        • 2012-12-09
        • 2021-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-25
        • 2016-02-22
        • 1970-01-01
        • 2022-01-24
        相关资源
        最近更新 更多