【问题标题】:chaining await with .then and try catch syntax用 .then 链接 await 并尝试 catch 语法
【发布时间】:2020-02-05 07:14:55
【问题描述】:

我有一个提交功能

const onSubmit = async (creditCardInput) => {
const { navigation } = this.props;
this.setState({ submitted: true });
let creditCardToken;

try {
  creditCardToken = await getCreditCardToken(creditCardInput);
  if (creditCardToken.error) {
    this.setState({ submitted: false});
    return;
  }
} catch (e) {
  this.setState({ submitted: false });
  return;
}


try {
  const obj = await subscribeUser(creditCardToken);
  console.log('returned obj', obj);
  try {
    const docRef = await this.db.collection("users").doc(this.user.email).set({
      id: this.user.uid,
      subscriptionId: obj.customerId,
      active: true
    });
    console.log("Document written with ID: ", docRef);
    this.navigateToScreen('HomeScreen');
  } catch (e) {
    console.log("Error adding document: ", e);
  }
} catch (error) {
  console.log('catch error', error);
  this.setState({ submitted: false, error: SERVER_ERROR, message: error });
}  
};

这是正常工作的 - 当 this.db.collection 调用失败时,捕获被实现意味着它会注销“添加文档时出错:”,e 见下面的代码sn-p

  try {
    const docRef = await this.db.collection("users").doc(this.user.email).set({
      id: this.user.uid,
      subscriptionId: obj.customerId,
      active: true
    });
    console.log("Document written with ID: ", docRef);
    this.navigateToScreen('HomeScreen');
  } catch (e) {
    console.log("Error adding document: ", e);
  }

但是,当我以不同的方式实现 subscribe 用户函数时(见下文),我不再使用 try catch 而是使用 .then 内部函数最终失败并且执行外部 catch 语句意味着它注销console.log('捕获错误', 错误);什么时候应该退出 console.log("Error added document:", errors); 这是为什么?它们不应该以相同的方式工作吗,这意味着上面和下面的代码 sn-p 应该以相同的方式工作 见下面的代码

await subscribeUser(creditCardToken).then((obj)=> {
this.db.collection("users").doc(this.user.email).set({
    id: this.user.uid,
    subscriptionId: obj.customerId,
    active: true
}).then((docRef) => {
    console.log("Document written with ID: ", docRef);
    this.navigateToScreen('HomeScreen');
}).catch((errors) => {
    console.log("Error adding document: ", errors);
});
}).catch((error) => {
    console.log('catch error', error);
    this.setState({ submitted: false message: error });
});

当 this.db.collections 成功解析 .then 时,只是添加了一条注释执行外部捕获而不是内部捕获

还向 this.db.collection 函数添加 return 并删除 await 对结果没有影响

【问题讨论】:

  • 您是否考虑过使用最后一段代码更好地使用缩进 - 因为它看起来像一个扁平的 .then/.catch/.catch 链,但显然不是跨度>
  • 试试return this.db.collection("users") .... 看看有没有效果
  • 顺便说一句,像这样同时使用 async/await 和 .then/.catch 几乎不是“正确的”
  • 在 SO 上缩进时遇到了问题,没有从编辑器中很好地复制 - 我会尝试返回这个,就我理解的“正确”方式而言,使用 try catch 对 async 和 await 更好,但它们应该可以工作与 promises 相同的方式,所以即使认为它可能不正确,我认为它应该仍然具有相同的功能
  • 缺少的return 可能会有所不同 - 你试过了吗?

标签: javascript firebase promise async-await


【解决方案1】:

有两种方法可以处理这个问题 - 将您的 set 函数转换为使用 async/await 语法,或者 return 您设置的函数到 subscribeUser 函数的下一个 then 声明。我会同时展示两者,但我更喜欢第二个,因为我不喜欢将 async/await 与 then/catch 混合使用。

const tempThis = this
subscribeUser(creditCardToken).then((obj)=> {
  // RETURN this promise and you'll get it in the next then statement
  return tempThis.db.collection("users").doc(tempThis.user.email).set({
    id: tempThis.user.uid,
    subscriptionId: obj.customerId,
    active: true
  })
}).then((docRef) => {
  console.log("Document written with ID: ", docRef);
  this.navigateToScreen('HomeScreen');
}).catch((errors) => {
  // This will catch the errors from subscribeUser AND from the set function
  console.log("Error adding document: ", errors);
});

或者只使用 async/await

try {
  const obj = await subscribeUser(creditCardToken)
  const docRef = await this.db.collection("users").doc(this.user.email).set({
    id: this.user.uid,
    subscriptionId: obj.customerId,
    active: true
  })
  console.log("Document written with ID: ", docRef);
  this.navigateToScreen('HomeScreen');
} catch (error) {
  // Handle your errors
}

【讨论】:

  • 谢谢 - 我会测试 - 虽然如果你使用关键字 await 或没有在理论上你应该仍然能够链接不应该没关系?这意味着 .then 正在使用 await
  • 是的,但是你的“set”函数返回一个promise,所以你需要把它返回给外部函数。这就是为什么您的代码不等待它完成以及为什么它会被内部的 then/catch 吹走的原因。对于 99% 的用例(可能是你和我的 100%),async/await 与 then/catch 是个人偏好。我只是个人不喜欢将链式与 async/await 混合使用 - 再次,个人喜好。
  • 我也同意——我比任何东西都在尝试——try catch 语法按预期对我有用,但想知道为什么你可以链式等待,但它的工作方式可能与常规 Promise 不同
  • 您可以链接多个then 语句,但带有异步的catch 将转到您的try/catch。所以你可以这样做: const docRef = await subscribeUser(creditCardToken).then((obj)=> { return this.db.collection("users").doc(this.user.email).set({ id: this. user.uid, subscriptionId: obj.customerId, active: true }) })
  • 嗨,我也是 Joe,我在 async 函数中使用常规 promise 尝试了上面的代码,即使添加 return 并删除 await,我仍然得到相同的结果——内部 promise 正在做外部承诺失败
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-06
  • 2021-10-17
  • 2020-01-02
  • 1970-01-01
  • 2018-08-24
  • 2021-04-10
相关资源
最近更新 更多