【问题标题】:Newbie question about JavaScript promises and "then" statements关于 JavaScript 承诺和“then”语句的新手问题
【发布时间】:2019-12-06 18:24:47
【问题描述】:

我对 JavaScript 还很陌生,我发现 promises 和“then”语句的概念真的很难确定。我正在使用 Firebase 的网站上工作,并且正在尝试从数据库中获取用户数据。这是我目前拥有的:

// Function that fetches a user's data from the database.
getUserData = function(uid) {
  var database = firebase.firestore();
  var docRef = database.collection('users').doc(uid);

  var userData = docRef.get().then(function(doc) {
    if (doc.exists) {
      return doc.data();
    } else {
      console.log("User does not exist.");
      return null;
    }
  }).catch(function(error) {
    console.log("Error getting document:", error);
  });

  return userData;
}

目前,此函数返回一个 Promise 对象。当我将对象记录到控制台时,它表示承诺状态已解决,其值是 doc.data() 的值。我真正想要的是将 doc.data() 的值通过“链”备份到 getUserData 函数,以便我可以返回并在其他地方使用它。有没有一种简单的方法可以做到这一点?我试图找到一种方法来从对象本身中获取 Promise 的“价值”,但我什么也没找到,到目前为止我还没有找到任何其他方法来做我想做的事。

我敢肯定它比看起来简单得多,而且我觉得问这种事情就像个白痴,但我已经搜索了几个小时,但我找到的解释都没有帮助.我将不胜感激任何建议。谢谢!

编辑:已解决!谢谢大家的帮助!以防万一这对将来偶然发现它的人有所帮助,我将把我的最终(工作)代码留在这里。不幸的是,无法从同步函数中调用它,但它最终足以满足我的目的:

// Function that fetches a user's data from the database.
async function getUserData(uid) {
  var database = firebase.firestore();
  var docRef = database.collection('users').doc(uid);

  var doc = await docRef.get();
  if (doc.exists) {
    return doc.data();
  } else {
    console.log("User does not exist.");
    return null;
  }
}

【问题讨论】:

  • 不,在返回时,promise 尚未解决 - 值是异步获取的。而且没有办法立即得到它们(没有时间机器)。你需要返回 Promise,并一直使用 Promise。
  • @Bergi 我认为他的意思是直接获得结果而不必使用.then
  • @jonatjano 是的,我是说这是不可能的。
  • @Bergi 有专门针对这个的 async/await
  • @jonatjano await 也使用thenasync 函数仍然返回一个承诺。它不会使任何东西同步,它只是 then 链的语法糖。

标签: javascript promise


【解决方案1】:

首先你要明白,Promise 主要用于异步操作,在异步操作解决之前,它们不存储值。 承诺不公开任何“get”方法来直接检索它们的值,而只公开一个 then 方法来在承诺解决后执行回调。因此,使用 Promise,您始终需要“等待”它解析读取值。

现在,你有两个选择:

首先是使用then()catch()的老办法。

你让你的函数返回一个 Promise(就像你做的那样)并且在你调用你的函数的地方,你可以使用 then 来执行一个带有结果的回调。

getUserData("anId").then((userData) => console.log('the async result is' + userData))

你也可以使用catch来处理错误:

getUserData("anId")
.then((userData) => console.log('the async result is' + userData))
.catch((error) => console.error('wooopsie : ' + error))

至于“新”的做事方式,你可以使用JS的asyncawait关键字来处理你的Promises。

基本上,声明为 async 的函数将始终返回一个 Promise 并定义一个允许使用 await 关键字的上下文。 await 将允许您像编写同步代码一样编写 Promise 处理。

async function(){
const userData = await getUserData("anId");
console.log('the async result is' + userData);

最后,如果你需要错误处理,你需要用 try-catch 包装 await 指令。

希望这会有所帮助。

【讨论】:

  • 他们不会在任何时候将价值存储在自己身上” - 实际上是的,当承诺兑现时,他们会这样做。这就是为什么你可以在同一个 Promise 上多次调用 .then()
  • 只是为了明确一点:从直接 Promises 更改为 async-await 使得某些人认为语法更直观,但不会改变底层调用的基本异步性质。没有魔法可以将异步处理变成同步处理。
  • 感谢您的解释!这比我能找到的其他东西更有意义。我最终使用了 async/await,并进行了一些摆弄(以及使一些以前编写的函数异步)我让它工作了。
  • 我不同意,在原始代码示例中,返回值 userData 是一个 Promise,在函数声明中没有任何异步。这是因为 then() 和 catch() 方法最终返回了 Promise 并进行了一些转换。
【解决方案2】:

使用 Promise 的原因是它们使异步代码更易于使用。不幸的是,如果您不习惯,代码仍然会有些棘手。在大多数情况下使用 async/await 可能会更好,因为它更容易使用,也可能更容易理解:

async function getUserData(uid) {
  var database = firebase.firestore();
  var docRef = database.collection('users').doc(uid);
  var doc = await docRef.get();
  if(doc.exists)
    return doc.data();
  return null;
}

这就是你将如何使用它:

// code to execute before
getUserData(uid).then(userData => {
  if(userData) {
  // code to execute after
  }
  else console.log("User does not exist.");
}).catch(error => {
  console.log("Error getting document:", error);
});

或者(异步/等待):

async function doSomething(uid) {
  // code to execute before
  const userData = await getUserData(uid);
  // code to execute after
}

带有自定义错误处理的异步/等待:

async function doSomething(uid) {
  // code to execute before
  try {
    const userData = await getUserData(uid);
    if(userData) {
    // code to execute after
    }
    else console.log("User does not exist.");
  }
  catch(error) {
    console.log("Error:", error);
  }
}

【讨论】:

  • 谢谢!通过一些摆弄(以及其他人的一些建议/解释),我得到了这个工作。我真的很感激!
【解决方案3】:

要从 Promise 中获取价值,您需要使用 .then,因此在您调用 getUserData 的行中获取数据时,您需要使用相同的构造 (getUserData.then((data) => {}))

【讨论】:

    猜你喜欢
    • 2023-03-15
    • 2019-07-11
    • 2014-03-21
    • 1970-01-01
    • 2012-09-30
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多