React-native and Firebase: Wait for Firebase data

2019-08-21 00:03发布

问题:

I am currently implementing an application which relies on Firebase data before it can continue. However, I often (unless I deliberately wait) get the result Cannot read property [property] of null. I very much suspect that this is because the firebase request could not be made before I call this object.

Now I am looking for methods to implement a rendez-vous, or a barrier, really anything that implements a checkpoint where all firebase data are received, before it continues. Is there anything in Javascript which helps me to do so, or any library, or any react-native library that helps me to achieve this?

My code looks as follows: (Fb is the firebase interface)

@action
  bookInterestedBike() {
    this.bookedBikeNo = this.interestBikeNo;
    this.downloadBikeObj();
    this.updateBikeDataStartRide();
    this.updateUserDataStartRide();
    //
    //This is where the firebase checkpoint / barrier should happen, and no progress should be made unless this data was fetched!
    //
    this.startTimer();
  }

@action
  downloadBikeObj() {
    Fb.staticBikes.child(String(this.bookedBikeNo)).once('value', (bikeObj) => {
      this.bikeObj = bikeObj.val();
      console.log("Save object is: ");
      console.log(this.bikeObj);
    });
  }

  updateBikeDataStartRide() {
    var updateVals = {}
    updateVals[this.interestBikeNo] = {
      bike_no: this.interestBikeNo,
      current_user: "self",
      positionLat: this.usrLat,
      positionLng: this.usrLng
    };
    Fb.bikes.update(updateVals);
    return false;
  };

  updateUserDataStartRide() {
    var updateVals = {}
    updateVals[this.uuid] = {
      bike_no: this.bookedBikeNo,
      uuid: this.uuid //TODO: remove this in deployment
    };
    Fb.users.update(updateVals);
    return false;
  };

On another component, this is the function that get's called (it is crucial that all data from updateBookedBikeBegin() is received before calling navigateToSuccessBookedBike()

  updateBookedBikeBegin() {
    this.userStore.bookInterestedBike();
    this.navigateToSuccessBookedBike();
  }

回答1:

For convenience using promises over callbacks is preferred for this situation. You need to return a promise in downloadBikeObj.

downloadBikeObj() {
    return Fb.staticBikes
      .child(String(this.bookedBikeNo))
      .once('value')
      .then(bikeObj => {
        this.bikeObj = bikeObj.val;
        console.log("Save object is: ");
        console.log(this.bikeObj);
      }); // return promise
}

And compose over the returned promise in bookInterestedBike.

bookInterestedBike() {
    this.bookedBikeNo = this.interestBikeNo;

    this.downloadBikeObj()
        .then(() => this.updateBikeDataStartRide())
        .then(() => this.updateUserDataStartRide())
        .then(() => this.startTimer());    
}

Reference:

https://firebase.googleblog.com/2016/01/keeping-our-promises-and-callbacks_76.html