3

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?"

Doug Stevenson
  • 297,357
  • 32
  • 422
  • 441
Flashman VC
  • 63
  • 1
  • 7
  • db.runTransaction returns a promise. It says so right in the API docs, but it seems you're not doing anything with it. https://cloud.google.com/nodejs/docs/reference/firestore/0.12.x/Firestore#runTransaction – Doug Stevenson Mar 06 '18 at 03:41
  • why don't you check `newPopulation <= 1000000` this in firestore rules?. Then i believe rules will throw the error while trying to update. – Hareesh Mar 06 '18 at 06:09
  • I did check and no error was thrown I removed it to make the code smaller. I also removed the "else return Promise.reject(" because it caused a syntax error as mentioned in the question. I wonder if that has anything to do with it? I cannot waste any more time on it, I'll leave it until I start system testing. – Flashman VC Mar 06 '18 at 08:26

2 Answers2

3

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);
    });
  }
Ankur
  • 33,367
  • 2
  • 46
  • 72
  • 1
    Thank you for answering but it returns null prior to returning the console.log message "Population increased to 118". The 118 shows how attempts I have made trying to get this to work. I have also put a " then" after the update statement which also failed. Surely I am not the only person who needs to update a field and get the result within the one transaction? – Flashman VC Mar 06 '18 at 04:29
0

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

Flashman VC
  • 63
  • 1
  • 7