Flashman VC
Flashman VC

Reputation: 63

How to get a Firestore transaction to return a promise?

I asked a question two days ago with a reply "Your method must return a Promise (or an Observable)."

I have altered my code to be exactly the same as the example at "https://firebase.google.com/docs/firestore/manage-data/transactions" but the problem is it passes the result as a console log but I need to wait for the write to complete at I need the result.

  orderIndex() {
    let db = this.firebase.firestore();
    var sfDocRef = db.collection("cities").doc("SF");
    db.runTransaction(function (transaction) {
      return transaction.get(sfDocRef).then(function (sfDoc) {
        if (!sfDoc.exists) {
          throw "Document does not exist!";
        }

        var newPopulation = sfDoc.data().population + 1;
        if (newPopulation <= 1000000) {
          transaction.update(sfDocRef, { population: newPopulation });
          return newPopulation;
        } else {
          return Promise.reject("Sorry! Population is too big.");
        }
      });
    }).then(function (newPopulation) {
      console.log("Population increased to ", newPopulation);
    }).catch(function (err) {
      // This will be an "population is too big" error.
      console.error(err);
    });
  }

I have spent a further two days trying to get a promise returned.

I have seen so many questions asking for help and receiving code suggestions in reply. Please help because I am new to this and have spent over four days on this problem.

By the way the code from firebase.google has an error in

return Promise.reject("Sorry! Population is too big.");

Error: "[ts] Property 'reject' does not exist on type '(resolver: (resolve: (val: IWhenable) => void, reject: (reason: any) => void, notify: (prog...'."

My previous question was at "How do I alter the promises in my function to stop it returning before the data arrives?"

Upvotes: 3

Views: 4131

Answers (2)

Flashman VC
Flashman VC

Reputation: 63

The following code updates the index, stores it back in firestore and returns the new number.

createOrderNo() {
    const getDbIndex = new Promise(
      (resolve, reject) => {
        if (!this.orderLive) {
          this.orderLive = true;
          const sfDocRef = this.db.collection('eOrderIndex').doc('orderIndex');
          sfDocRef.get().
            then(function (sfDoc) {
              if (!sfDoc.exists) {
                throw "Document does not exist!";
              }
              console.log('sfDoc.data()', sfDoc.data()['index'])
              let index = sfDoc.data()['index'] + 1;
              sfDocRef.update({ index: index });
              resolve(index);
            })
        } else {
          const reason = new Error('Already live');
          reject(reason);
        }
      })
    async function show(index) {
      return new Promise(
        (resolve, reject) => {
          var message = 'New index ' + index;
          resolve(message);
        }
      );
    };

    // call the promise
    async function runPromise() {
      try {
        console.log('Before get');

        let index = await getDbIndex;
        let message = await show(index);

        console.log(message);
        console.log('After get');
      }
      catch (error) {
        console.log(error.message);
      }
    }

    (async () => {
      await runPromise();
    })();
  }

Many thanks to Jecelyn Yeen at scotch.io

Upvotes: 0

Ankur
Ankur

Reputation: 33637

Your function is not returning the promise and also in the then case you are not returning any value.

Try this:

  orderIndex() {
    let db = this.firebase.firestore();
    var sfDocRef = db.collection("cities").doc("SF");
    return db.runTransaction(function (transaction) { //Return here
      return transaction.get(sfDocRef).then(function (sfDoc) {
        if (!sfDoc.exists) {
          throw "Document does not exist!";
        }

        var newPopulation = sfDoc.data().population + 1;
        if (newPopulation <= 1000000) {
          transaction.update(sfDocRef, { population: newPopulation });
          return newPopulation;
        } else {
          return Promise.reject("Sorry! Population is too big.");
        }
      });
    }).then(function (newPopulation) {
      console.log("Population increased to ", newPopulation);
      return newPopulation; //Return the value
    }).catch(function (err) {
      // This will be an "population is too big" error.
      console.error(err);
    });
  }

Upvotes: 3

Related Questions