【问题标题】:Can't change code from .then to async/await无法将代码从 .then 更改为 async/await
【发布时间】:2020-06-25 14:23:38
【问题描述】:

试图改变.then,像这样:

User.prototype.login = () => {
  return new Promise((resolve, reject) => {
    this.cleanup();
    usersCollection
      .findOne({ username: this.data.username })
      .then((attemptedUser) => {
        if (attemptedUser && attemptedUser.password == this.data.password) {
          resolve("logged in");
        } else {
          reject("invalid something");
        }
      })
      .catch(() => {
        reject("Please, try again later");
      });
  });

第一个效果很好,但是当我尝试将其更改为 async/await 时,如下所示:

User.prototype.login = () => {
  return new Promise(async (resolve, reject) => {
    this.cleanup();
    try {
      const attemptedUser = await usersCollection.findOne({ username: this.data.username });
      if (attemptedUser && attemptedUser.password == this.data.password) {
        resolve("logged in");
      } else {
        reject("invalid something");
      }
    } catch {
      reject("Please, try again later");
    }
  });
};

它给我一个错误,this.cleanup() 不是一个函数,经过几次尝试,我意识到异步以某种方式改变了“this”。

你能帮帮我吗,我在哪里出错了?

【问题讨论】:

  • 为什么要将 promise 和 async/await 放在一个地方?
  • 我意识到 async 会以某种方式改变“this”。 async 与 this 的值的设置方式无关
  • 这与async关键字的使用无关。如果此方法中的this 应该是User 对象,那么您可能会在几个地方出错。对于初学者,User.prototype.login 不应该是箭头函数,因为它不会传递this 中的实例值。它应该是一个常规的函数声明第二,你必须确保你正确地调用了someUserObj.login(),所以你必须向我们展示调用代码,让我们看看你是否正确地这样做了。

标签: javascript node.js


【解决方案1】:

您的代码中有 2 个问题:

  1. prototype 对象上定义的函数应该是常规函数而不是箭头函数,因为在对象上定义的函数被用作方法,即它们内部的 this 值是指构造函数或类的实例。使用箭头函数会设置不正确的 this 值,这很可能是您的代码出错的原因。

  2. 您将 promise-chainingasync-await 语法混合在一起。async 函数总是返回 Promise,因此不要显式返回 Promise 对象,而是将 login 函数设为 async 函数并返回来自函数的字符串,这与使用字符串调用 resolve() 函数相同。要拒绝承诺,请从 async 函数中抛出错误。

这就是你应该如何定义login函数

User.prototype.login = async function() {
    this.cleanup();

    try {
      const attemptedUser = await usersCollection.findOne({username: this.data.username});

      if (attemptedUser && attemptedUser.password == this.data.password) {
        return "logged in";
      }

      throw new Error("invalid something");

    } catch (error) {
      console.log("Please, try again later");
      throw error;
    }
};

【讨论】:

  • 这通常是正确的(尽管您应该为拒绝抛出错误对象),但这如何解决this.cleanup()this 的值,这是问题的重点?跨度>
  • returnconsole.log 代替promise 拒绝是不太可取的。你应该抛出一个错误,在一个异步函数中,这使得 promise 被错误对象拒绝,这更接近原始行为并且是一个很好的模式。
  • @jfriend00 它与this 的值无关,正如我在回答中提到的那样,login 函数内的this 的值将与周围环境相同函数已定义。
  • @Klaycon 我同意。已编辑,缺少 throw 声明。
  • 是的,箭头函数中this 的词法值可能是错误的。我不相信当他们更改的只是async 关键字时,他们的代码会中断。
猜你喜欢
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
  • 2019-12-14
  • 2021-04-10
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多