FabricioG
FabricioG

Reputation: 3320

React Native .then seems to be running out of order

I currently have the following method in a react native class, however I think this would apply to JS in general but I might be wrong:

  dbGetTemplateOptions = () => {
    let dataArray = [];
    let subcategories = this.state.subcategories;

    subcategories.forEach(item => {
      let getSubValues = new Promise(function(resolve, reject) {
        resolve(item);
      })
      getSubValues.then((item) => this.dbGetValues(item.subCatId))
      getSubValues.then((value) => console.log(2))
    });
  }

According to my limited js knowledge of promises, in the above I'm resolving a promise and running getSubValues.then() which would mean that each of the .then methods run AFTER the method returns.

In the above code I call the method dbGetValues(item.subCatId) Which is this:

  async dbGetValues(subCatId) {
    let subValues = [];
    let result = await db.transaction(tx => {
      tx.executeSql(
        'SELECT * FROM dr_template_relational '
        + ' INNER JOIN  dr_report_categorie_values on dr_report_categorie_values.id = dr_template_relational.value_id'
        + ' WHERE dr_template_relational.subcategory_id = ' + subCatId + ' AND dr_template_relational.template_id = ' + this.state.currentTemplateId,
        [],
      (trans, result) => {
        const sqLiteResults = result.rows._array;

        sqLiteResults.forEach(el => {
          subValues.push({ subCategoryId: subCatId, values: el.value_id, name: el.name, narrative: el.narrative });
        })
      });
    },
    (err) => console.error(err),
    () => {
      console.log(1);
      return subValues;
    }
  );
  return result;
  }

Notice my console.log(2) is after the then which is calling the method. Inside the method also notice I have console.log(1). I would expect these to run in order since I'm waiting for it to finish before the next then runs. I realize I'm incorrect because the console.log is actually.

2
2
1
1

Upvotes: 0

Views: 185

Answers (1)

dbramwell
dbramwell

Reputation: 1326

  dbGetTemplateOptions = () => {
    let dataArray = [];
    let subcategories = this.state.subcategories;

    subcategories.forEach(item => {
      let getSubValues = new Promise(function(resolve, reject) {
        resolve(item);
      })
      getSubValues.then((item) => this.dbGetValues(item.subCatId))
      getSubValues.then((value) => console.log(2))
    });
  }

You're resolving the promise before actually calling the asynchronous dbGetValues function. This is why the then triggers before the callbacks of dbGetValues do.

It's hard to know what changes to make without more context of what you're tying to do, but I think you might actually want something like:

  dbGetTemplateOptions = () => {
    let dataArray = [];
    let subcategories = this.state.subcategories;

    subcategories.forEach(item => {
      let getSubValues = new Promise(async (resolve, reject) => {
        const result = await this.dbGetValues(item.subCatId)
        resolve(result);
      })
      getSubValues.then((value) => console.log(2))
    });
  }

Or to try to simplify even more:

  dbGetTemplateOptions = () => {
    let dataArray = [];
    let subcategories = this.state.subcategories;

    subcategories.forEach(async (item) => {
      const result = await this.dbGetValues(item.subCatId)
      // Do something with result here
      console.log(2)
    });
  }

Obviously this is based on assumptions of what you're doing

Upvotes: 1

Related Questions