【问题标题】:Get data using await async without try catch使用 await async 获取数据而不使用 try catch
【发布时间】:2018-10-17 00:41:22
【问题描述】:

我正在尝试使用没有 try-catch 的 await-async:

const getUsers = async (reject, time) => (
  new Promise((resolve, reject) => {
    setTimeout(() => {
      if (reject) {
        reject(....)
      }
      resolve(.....);
    }, time);
  })
);

module.exports = {
  getUsers ,
};

使用 try-catch 块,它看起来像这样:

const { getUsers } = require('./users');

const users = async () => {
  try {
    const value = await getUsers(1000, false);
    .....
  } catch (error) {
    .....
  }
}

users();

如何在不使用 try-catch 块的情况下编写相同的代码?

【问题讨论】:

  • 您必须在某处处理错误。如果你想避免用户函数中的 try-catch,那么你必须在 getUsers 中捕获所有可能的错误
  • 这里你可以这样做stackoverflow.com/a/61833084/6482248它看起来更干净

标签: javascript typescript async-await try-catch


【解决方案1】:

使用 promise 函数 then-catch 来简化过程,我使用了这个工具:

// utils.js

const utils = promise => (
  promise
    .then(data => ({ data, error: null }))
    .catch(error => ({ error, data: null }))
);

module.exports = utils;

然后

const { getUsers } = require('./api');
const utils = require('./utils');

const users = async () => {
  const { error, data } = await utils(getUsers(2000, false));
  if (!error) {
    console.info(data);
    return;
  }
  console.error(error);
}

users();

在不使用 try-catch 块的情况下,我得到了相同的输出,这种方式可以更好地理解代码。

【讨论】:

  • 用 Mongoose 尝试了这种方法来将数据保存到集合中 ~ .save() 方法。尝试捕获输出不匹配。用这种方法获取数据undefined,而try块得到正确的响应。
【解决方案2】:

如果您对错误情况有有效的默认值,您可以在 getUsers 承诺上使用 catch 方法,然后 await 将处理其错误的承诺

const users = async () => {
    const value = await getUsers(1000, false).catch(e => null);
}

虽然这种方法应该有效,但应注意,这可能会掩盖getUsers 返回null 与引发错误时的情况,您仍需要检查null 或获取空访问权限错误。总而言之,对于大多数情况,我会坚持使用try { .. } catch (e) { ... }

【讨论】:

    【解决方案3】:

    我发现一个名为 await-to-js 的包也可以提供帮助。

    import to from 'await-to-js';
    
    const [err, users] = await to(getUsers());
    if(err) doSomething();
    

    这个想法就像 Lyes CHIOUKH 的方法,只是一个包装器。在此处复制source code

    /**
     * @param { Promise } promise
     * @param { Object= } errorExt - Additional Information you can pass to the err object
     * @return { Promise }
     */
    export function to<T, U = Error> (
      promise: Promise<T>,
      errorExt?: object
    ): Promise<[U | null, T | undefined]> {
      return promise
        .then<[null, T]>((data: T) => [null, data])
        .catch<[U, undefined]>((err: U) => {
          if (errorExt) {
            Object.assign(err, errorExt);
          }
    
          return [err, undefined];
        });
    }
    
    export default to;
    

    【讨论】:

      【解决方案4】:

      延伸到 L Y E S - C H I O U K H 的答案:

      Utils 函数实际上是正确的,但请确保在 promise 之前添加 return 关键字,如下所示:

      // utils.js
      
      const utils = promise => (
        return promise
          .then(data => { [data, null]; })
          .catch(error => { [null, error]; });
      );
      
      module.exports = utils;

      主代码调用时:

      let resonse, error; // any variable name is fine make sure there is one for error and the response
      
      [response, error] = await utils(any_function()); // Make sure that inside the tuple, response is first and error is last like: [response, error].
      if (error) console.log(error);
      
      // -- Do Whatever with the Response -- //

      使用我的方法会给您带来以下好处:

      1. 您自己的变量名称。
      2. 使用 Typescript 时不会遇到类型安全问题。
      3. 强类型代码的好理由。

      就个人而言,我最近一直在我的代码中使用它,并且减少了一些令人头疼的问题,我的代码更简洁,我不必坚持使用相同的变量名,尤其是在处理大型代码库时。

      快乐编码:)

      再见!

      【讨论】:

      • 很好的回应!请问(1)您是否仍然使用这种方法,以及(2)是否有任何我们应该知道的问题或陷阱?我已经开始使用它了,我真的很喜欢它!
      • @themthem 我已经迟到了,但是,不,我不再使用这种方法,而是将 await 语句包装在 try-catch 循环中,并在 @ 中处理错误987654325@ 部分,如果您使用打字稿,这种方法特别好。
      【解决方案5】:

      如果你有上面这样的单行 async/await 函数,那么这对你来说是干净的代码:

      const getUsers = async (time, shouldReject=false) => {
          return new Promise((resolve, reject) => {
            setTimeout(() => {
              if (shouldReject) {
                reject(Error('Rejected...'));
              } else {
                resolve(["User1", "User2"]);
              }
            }, time);
          });
      }
      
      const userOperation = users => {
        console.log("Operating user", users);
      }
      
      // Example 1, pass
      getUsers(100)
          .then(users => userOperation(users))
          .catch(e => console.log(e.message));
      
      // Example 2, rejected
      getUsers(100, true)
          .then(users => userOperation(users))
          .catch(e => console.log(e.message));

      对于单个async 函数中的多个await,最好有如下try/catch 块:

      const users = async () => {
          try {
              const value = await getUsers(1000, false);
              const value1 = await getUsers2(1000, false);
              ...
          } catch (error) {
              ...
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2021-08-28
        • 2023-01-17
        • 2017-11-23
        • 2020-09-07
        • 2019-09-30
        • 2020-02-20
        相关资源
        最近更新 更多