关于JavaScript承诺和“然后”语句的新手问题

时间:2019-07-29 11:57:38

标签: javascript promise

我对JavaScript还是很陌生,并且发现promise和“ 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;
  }
}

3 个答案:

答案 0 :(得分:1)

首先,您必须了解Promise主要用于异步操作,并且它们不存储值UNTIL异步操作已解决。 承诺不公开任何“ 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的 async await 关键字来处理您的承诺。

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

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

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

希望这会有所帮助。

答案 1 :(得分:1)

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

答案 2 :(得分:0)

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