Oliver D
Oliver D

Reputation: 2889

How to await two requests with Promise.all then invoke other functions in callback?

I'm trying to wait for two requests I get data from firebase DB and set into a state,

I want after two requests Done, concatenate result data in one array,

So I tried to push two requests in an array then use

> Promise.all(promises).then(()=>this.updateData());

but it does not work as expected, I can see in the console updateData() invoked before " Code here

 fetchOrders = async () => {
         ....
 let promises = [];
    promises.push(
      //  First service orders
      database()
        .ref(
          `Providers/CategoriesOrders/${this.state.serviceName[0] ||
            this.state.serviceStorage[0]}`,
        )
        .on('value', this.ordersCallbackOne),
    );



promises.push(
      // Second service orders
      database()
        .ref(
          `Providers/CategoriesOrders/${this.state.serviceName[1] ||
            this.state.serviceStorage[1]}`,
        )
        .on('value', this.ordersCallbackTwo),
    );

  Promise.all(promises).then(() => this.updateData());
  };



ordersCallbackTwo = snapshot => {
    let orderArr = [];
    snapshot.forEach(childSnapshot => {
      orderArr.push({
        snapshotKey: childSnapshot.key,
        username: childSnapshot.val().username,
      });
    });
    this.setState({orderServiceTwo: orderArr}, () =>
      console.log('2', this.state.orderServiceTwo), // it's log data here
    );
  };

the function I want to invoke after two requests Done.

  updateData = () => {
    // if (this.rejectedOrders?.length >= 1) {
    //   const orders = this.state.orders.filter(
    //     order => !this.rejectedOrders.some(key => order.snapshotKey === key),
    //   );
    //   this.setState({orders, loading: false});
    //   return;
    // }

    console.log('ordersOne!', this.state.orderServiceOne); // empty!

    const order1IDs = new Set(
      this.state.orderServiceOne.map(({snapshotKey}) => snapshotKey),
    );
    console.log('order1IDs', order1IDs);
    const combined = [
      ...this.state.orderServiceOne,
      ...this.orderServiceTwo?.filter(
        ({snapshotKey}) => !order1IDs.has(snapshotKey),
      ),
    ];
    console.log('combined', combined);
    this.setState({
      orders: combined,
      loading: false,
    });
  };

Upvotes: 0

Views: 130

Answers (1)

Doug Stevenson
Doug Stevenson

Reputation: 317760

on('value') doesn't return a promise and won't work here. It's only used to attach a listener to a query, and will receive results indefinitely until call off().

Instead, you should use once('value'), which executes the query a single time and returns a promise when it completes.

Upvotes: 2

Related Questions