Получить асинхронное значение из пожарного магазина - PullRequest
0 голосов
/ 19 марта 2019

Я борюсь с асинхронными операциями.Я пытаюсь просто получить значение из firestore и сохранить его в переменной.

Мне удается получить значение, я даже могу сохранить его в переменной, когда я делаю это специально (используйте переменную в getфункция), но мне кажется, что я не могу должным образом управлять ожиданием при попытке сохранить его гибким способом:

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 в моем коде, я получаю

{}

Изображение от бота Telegram, где я пытаюсьиспользуйте helpMessage в качестве ответа на команду '/ help'.

Я проверил: получение значения из облачного пожарного хранилища , Firebase Firestore get () async / await, получить асинхронное значение из справки пожарной базы Firebase и большинстваrtantly Как мне вернуть ответ от асинхронного вызова? .Они либо имеют дело с несколькими документами (используя forEach), не затрагивают асинхронную природу моей проблемы или (в последнем случае), я просто не понимаю природу ее.

Кроме того, кажется, что nodejs и firestoreБыстро развиваться и находить хорошую, актуальную документацию или примеры сложно.Любые указатели очень ценятся.

Ответы [ 3 ]

2 голосов
/ 19 марта 2019

У вас все неправильно.Это гораздо проще, чем вы думаете.

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 выше.

В обработчике обещаний (внутри обратного вызова .then()) верните значение, указывающее на успех, или отклоненное обещание, чтобы указать на ошибку.Это «внутренний» return выше.Вместо возврата отклоненного обещания вы также можете throw выдать ошибку, если хотите.

Теперь у вас есть функция возврата обещания.Вы можете использовать его с .then() и .catch():

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

или await внутри функции async в блоке try / catch, если вам это нравится больше:

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

Если вы хотите использовать async / await с функцией 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 голос
/ 19 марта 2019

Поскольку функция getValues возвращает обещание, вам необходимо await получить функцию getValues, в то время как вызывает it.

Изменить 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 areпросто синтаксический сахар для обещаний.Асинхронные функции возвращают обещание (или AsyncFunction более точно), которое необходимо разрешить, чтобы использовать его вложенное значение.

См. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function

0 голосов
/ 19 марта 2019

Наконец-то удалось заставить его работать.Спасибо за вклад 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) и форматирование определенно помогли мне понять структуру.Надеюсь, кому-то еще это пригодится, когда вы начнете поиграться с узлом и базой огня.

...