Firebase транзакции вы должны вернуть обещание - PullRequest
0 голосов
/ 28 сентября 2018

Я пытаюсь выяснить, как записывать транзакции в базу данных firebase из углового приложения 6 / машинописного текста.

Один рабочий пример, который я использую в качестве руководства, следующий:

const transactions = [];

return db.runTransaction(function(transaction) {
            // const promises = [];
            descriptionsInDB.forEach(dbDescription => {
                if (dbDescription.matched === false) {
                    // item wasn't found, so add the item to the transaction.
                    const phraseItem: PhrasesDB = {
                        query: dbDescription.description,
                        updatedAt: Date.now(),
                        createdAt: Date.now(),
                        workflows: {
                            [workflowId]: true
                        }
                    };
                    const newPhrasesRef = phrasesCol.doc();
                    transactions.push(transaction.set(newPhrasesRef, phraseItem));
                } else {
                    if (dbDescription.data.workflows && dbDescription.data.workflows[workflowId]) {
                        // do nothing, this phrase is already part of the record.
                    } else { // update the workflows that are part of the record.
                        const workflows = { 
                            workflows: {
                                [workflowId]: true
                            }
                         };
                        const phrasesRef = phrasesCol.doc(dbDescription.dbId);
                        transactions.push(transaction.update(phrasesRef, workflows));
                    }
                }
            });

            return Promise.all(transactions); 
        })

Ключевые элементы, которые я определил, следующие:

1) Создайте массив для хранения ваших транзакций: const Transactions = [];

2) Начните транзакцию: return db.runTransactions (функция (транзакция) {…

3) Выполнить запрос к базе данных, используя транзакцию :action.set (newPhraseRef, фразуItem);

4) Передать транзакцию, возвращенную из запроса, вмассив транзакций: Transactions.push (Transactions.set (newPhraseRef, фразуItem));

5) Вернуть обещание с массивом транзакций: вернуть Promise.all (транзакция);

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

        const pendingRef = `Pending/${req.query.inviteId}`;
        const acceptance = {
          'cryptoInvitationAcceptance': req.body.cryptoInvitationAcceptance,
          'reason': (req.body.reason !== undefined ? req.body.reason : '')
        }
return db.runTransaction(function(t) {
          const transArray = [];
          const docRef = db.collection('Pending').doc(req.query.inviteId);
          transArray.push(t.set(docRef, acceptance));
          return Promise.all(transArray);
        }).then(result => {
          console.log('result = ', result);
        }).catch(err => {
          console.log('err = ', err);
        });

Но она всегда идет в блок catch и выводит сообщение:

err = Ошибка: Вы должны вернуть Promise в своей транзакции () - обратный вызов.

Но Я ЕСМЬ возвращаю обещание, не так ли?Строка: return Promise.all (transArray) - это обещание, которое я возвращаю.Нет

Ответы [ 2 ]

0 голосов
/ 30 сентября 2018

Оказывается, это лучший способ сделать это:

      return t.get(pendingDocRef).then(data => {
        t.set(pendingDocRef, acceptance, {merge:true});
      });

Функция get (...) возвращает запрашиваемое обещание, поэтому set (...) недолжен.

Мне это не нравится.Я все еще думаю, что я должен быть в состоянии сделать набор в транзакции самостоятельно (то есть без get).

Я также обнаружил, что этот сорт работает:

return t.set(...).commit();

Функция commit () также возвращает обещание, но затем я получаю действительно странное поведение: транзакция повторяется снова и снова, пока она не войдет в блок catch с ошибкой с эффектом «транзакция истекла».Тем не менее, данные передаются в базу данных, поэтому, если вы не возражаете против ошибки (просто дайте ей пройти), commit () тоже работает.

Подробности см. В этом посте: транзакция firebaseповторяется при совершении

0 голосов
/ 28 сентября 2018

Пожалуйста, прочитайте документацию для Transaction set() - обещание не возвращается.Это, вероятно, сбивает с толку Firestore SDK, поскольку вы возвращаете Promise.all() массива вещей, которые не являются обещаниями.Поэтому, возможно, он думает, что вы вернули ошибку.

Возможно, вам вообще не нужно ничего возвращать из функции обработчика транзакций.Просто позвоните set() и покончите с этим.Вам нужно только что-то вернуть из обработчика транзакций, если вы хотите передать это значение вызывающей стороне runTransaction через обещание, которое он возвращает.

Кстати, в первом примере вы не должныне собирать обещания в массив, который определен вне функции-обработчика.Это может вызвать проблемы, если обработчик транзакций запускается более одного раза.В документации, на которую я ссылался, говорится:

Не изменяйте состояние приложения внутри функций транзакции.Это создаст проблемы параллелизма, поскольку функции транзакций могут выполняться несколько раз и не гарантированно будут выполняться в потоке пользовательского интерфейса.

Этот массив вне транзакции будет считаться «состоянием приложения», посколькувнутри самой функции.

...