从Firestore获取异步值

时间:2019-03-19 10:46:35

标签: node.js function asynchronous google-cloud-firestore

我正在努力进行异步操作。我试图从firestore中获取一个值并将其存储在var中。

我设法接收该值,当我专门执行该操作时,甚至可以将其保存在var中(使用get函数中的var),但是在尝试将其保存到a中时,我似乎无法正确地管理await灵活的方式:

async function getValues(collectionName, docName,) {
console.log("start")
var result;
var docRef = await db.collection(collectionName).doc(docName).get()
  .then(//async// (tried this as well with async) function (doc) {
    if (doc.exists) {
      console.log("Document data:", doc.data());
      result = doc.data().text;
      console.log(result);
      return //await// (this as well with async) result;
    } else {
      // doc.data() will be undefined in this case
      console.log("No such document!");
      result = "No such document!";
      return result;
    }
    console.log("end");
  }).catch (function (err) {
    console.log('Error getting documents', err);
  });
};

helpMessage = getValues('configuration','helpMessage');

注意:doc.data().text -> "text"是存储我的值的字段的名称。在这里我必须使用.value吗?

我在控制台中得到的结果是:

信息:文档数据:{文本:“数据库中的正确文本”}
信息:来自数据库的正确文本

但是在我的代码中使用helpMessage会得到

{}

Image from the Telegram bot where I am trying to use the helpMessage as a response to the '/help' command.

我已经检查过:getting value from cloud firestoreFirebase Firestore get() async/awaitget asynchronous value from firebase firestore reference,最重要的是How do I return the response from an asynchronous call?。他们要么处理多个文档(使用forEach),要么不解决我的问题的异步性质,要么(最后一种情况),我只是无法理解它的性质。

此外,nodejs和firestore似乎都在快速发展,并且很难找到好的,最新的文档或示例。任何指针都非常有用。

3 个答案:

答案 0 :(得分:2)

您遇到错误的方法。它比您想象的要容易得多。

function getValues(collectionName, docName) {
    return db.collection(collectionName).doc(docName).get().then(function (doc) {
        if (doc.exists) return doc.data().text;
        return Promise.reject("No such document");
    }};
}

如果函数返回一个承诺(例如db.collection(...).doc(...).get()),则返回该承诺。这是上面的“外部” return

在Promise处理程序中(在.then()回调内部),返回一个值以指示成功,或者返回一个被拒绝的Promise以指示错误。这是上面的“内部” return。如果您愿意,也可以throw而不是返回被拒绝的承诺。

现在,您具有了兑现承诺的功能。您可以将其与.then().catch()一起使用:

getValues('configuration','helpMessage')
    .then(function (text) { console.log(text); })
    .catch(function (err) { console.log("ERROR:" err); });

await在try / catch块的async函数中,如果您更喜欢:

async function doSomething() {
    try {
        let text = await getValues('configuration','helpMessage');
        console.log(text);
    } catch {
        console.log("ERROR:" err);
    }
}

如果您想通过getValues()函数使用异步/等待,则可以:

async function getValues(collectionName, docName) {
    let doc = await db.collection(collectionName).doc(docName).get();
    if (doc.exists) return doc.data().text;
    throw new Error("No such document");
}

答案 1 :(得分:1)

由于getValues函数返回了一个Promise,因此您需要在调用时使用await getValues函数。

像这样更改getValues-

function getValues(collectionName, docName,) {
  console.log("start")
  var result;
  return db.collection(collectionName).doc(docName).get()
    .then(function (doc) {
      if (doc.exists) {
        console.log("Document data:", doc.data());
        result = doc.data().text;
        console.log(result);
        return result;
      } else {
        // doc.data() will be undefined in this case
        console.log("No such document!");
        result = "No such document!";
        return result;
      }
    }).catch (function (err) {
      console.log('Error getting documents', err);
    });
  };

然后像这样使用getValues-

helpMessage = await getValues('configuration','helpMessage');

说明-

async, await只是Promises的语法糖。异步函数返回一个Promise(或更准确地说是AsyncFunction),需要使用它的包含值对其进行解析。

请参见https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

答案 2 :(得分:0)

最终设法使其工作。感谢您输入Tomalak!

getValues(help.collectionName, help.docName)
  .then((text) => {
    console.log(text);
    help.message = text;
   })
  .catch((err) => { console.log("Error: ", err); });

function getValues(collectionName, docName) {
  return db.collection(collectionName).doc(docName).get().then((doc) => {
    if (doc.exists) {
      return doc.data().text;
    }
    else {
      return Promise.reject("No such document");
    }});
  }

bot.help((ctx) => ctx.reply(help.message));

不幸的是,我无法指出确切的原因。一些小的修复(在console.log中缺少逗号)和格式肯定可以帮助我理解结构。希望其他人在开始使用node和firebase时会觉得有用。