简体   繁体   English

关于JavaScript promise和“ then”语句的新手问题

[英]Newbie question about JavaScript promises and “then” statements

I'm fairly new to JavaScript, and I'm finding the concept of promises and "then" statements really hard to pin down. 我对JavaScript相当陌生,并且发现promise和“ then”语句的概念很难确定。 I'm working on a website using Firebase, and I'm trying to get user data from the database. 我正在使用Firebase的网站上工作,并且试图从数据库中获取用户数据。 Here's what I have at the moment: 这是我目前所拥有的:

// 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;
}

Currently, this function returns a Promise object. 当前,此函数返回Promise对象。 When I log the object to the console, it says that the promise status is resolved and its value is the value of doc.data(). 当我将对象记录到控制台时,它说承诺状态已解决,其值是doc.data()的值。 What I really want is to pass the value of doc.data() back up the "chain" to the getUserData function so that I can return and use it elsewhere. 真正想要的是将doc.data()的值传递回“链”上,传递给getUserData函数,以便我可以在其他地方返回并使用它。 Is there a simple way to do this? 有没有简单的方法可以做到这一点? I've tried to find a way to get the "value" of a Promise out of the object itself, but I've found nothing, and so far I have failed to find any other way to do what I want. 我试图找到一种从对象本身中获取Promise的“值”的方法,但是我什么也没发现,到目前为止,我还没有找到其他方法来做自己想要的事情。

I'm sure it's a lot simpler than it seems, and I feel like an idiot for asking this sort of thing, but I've been searching for a couple of hours and none of the explanations I've found are helping. 我敢肯定,这比看起来要简单得多,我觉得这是个白痴,但是我一直在寻找几个小时,但我发现的任何解释都无济于事。 I would greatly appreciate any advice. 我将不胜感激任何建议。 Thanks! 谢谢!

Edit: Solved! 编辑:解决了! Thanks for the help, everyone! 谢谢大家的帮助! Just in case this helps someone in the future who stumbles upon it, I'm leaving my final (working) code here. 以防万一这对将来偶然发现它的人有所帮助,我在这里保留我的最终(工作)代码。 Unfortunately there's no way to call it from a synchronous function, but it ended up being good enough for my purposes: 不幸的是,无法从同步函数中调用它,但是对于我的目的而言,它最终已经足够好了:

// 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;
  }
}

First you must understand that Promise are mainly used for asynchronous operation, and they do not store the value UNTIL the asynchronous operation is resolved. 首先,您必须了解Promise主要用于异步操作,并且它们不存储值UNTIL来解析异步操作。 Promises to not expose any "get" method to retrieve directly their value but only a then method to execute a callback once the promise is resolved. 承诺不公开任何“ get”方法以直接检索其值,而是仅使用一个then方法来解决承诺后执行回调。 Thus, with Promise you always need to "wait" for it to have resolved to read the value. 因此,使用Promise,您始终需要“等待”它解决读取值的问题。

Now, you have two choices : 现在,您有两种选择:

The first is to use the old way of then() and catch() . 第一种是使用then()catch()的旧方法。

You make your function return a Promise (like you did) and where you call your function, you can use then to execute a callback with your result. 您使函数返回Promise(就像您所做的一样),并在调用函数的位置使用, 然后使用结果执行回调。

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

You can also use catch to handle the error : 您还可以使用catch处理错误:

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

As for the "new" way of doing things, you can use the async and await keywords of JS to handle your Promises. 至于“新”的做事方式,您可以使用JS的asyncawait关键字来处理您的Promises。

Basically, a function declared async will always return a Promise and will define a context allowing to use the await keyword. 基本上,声明为异步的函数将始终返回Promise,并将定义允许使用await关键字的上下文。 And await will allow you to write your Promise handling just like synchronous code. 等待将使您可以像同步代码一样编写Promise处理。

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

Finally, if you need error handling, you will need to wrap the await instruction with a try-catch. 最后,如果您需要错误处理,则需要使用try-catch包装await指令。

Hope this helps. 希望这可以帮助。

The reason for using promises is that they make asynchronous code easier to work with. 使用promise的原因是它们使异步代码更易于使用。 Unfortunately the code can still be a little tricky if you're not used to it. 不幸的是,如果您不习惯该代码,它仍然会有些棘手。 You're probably better off using async/await in most situations as it will be easier to work with and also probably easier to understand: 在大多数情况下,最好使用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;
}

This is how you would use it: 这是您将如何使用它:

// 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);
});

Alternatively (Async/Await): 或者(异步/等待):

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

Async/Await with custom error handling: 异步/等待与自定义错误处理:

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);
  }
}

为了从promise获得价值,您需要使用.then ,因此在您的情况下,要在调用getUserData的行中获取数据,您需要使用相同的构造( getUserData.then((data) => {})

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM