1

My question is about unrecognized behavior of a react app. I wrote promises for API calls and exported them in one file as many components will use them. Problem is that those exported calls are executed even before I call them on app load.

//in commonAPI.js with other exports of similar promises
export var loadDesignationTypes = new Promise(function (resolve, reject) {

    axios.get('http://localhost:7002/commonAPI/getDesignations')
        .then(response => {
            if (response.data.success) {
                var designationObjAr = response.data.resultEmployeeDesignations;
                resolve(designationObjAr);
            }
        }).catch(function (error) {
            console.log("designation err " + error);
            reject(error)
        });
});

Inside components :

import { loadDesignationTypes, loadDepartmentTypes,
          loadLocationTypes, loadMaritialStatus } from '../../../CommonAPIs';

 //in a function
 const results = await Promise.all([loadDesignationTypes,
            loadDepartmentTypes,loadLocationTypes, loadMaritialStatus]);

What confuses me even more is that other promise exports which are not called inside component who resides in same file with called promise are executed as well.

hdk
  • 720
  • 2
  • 9
  • 19

1 Answers1

2

The module is currently running the new Promise(.. block synchronously, when the module's code is run, while the interpreter is trying to figure out what each module imports and exports. If you want the axios.get to run on demand, rather than automatically, you should export a function that creates a Promise when called, rather than a plain Promise.

You should also take care not to use the explicit Promise construction antipattern - simply return the Promise chain instead:

export var loadDesignationTypes = () => axios.get('http://localhost:7002/commonAPI/getDesignations')
  .then(response => {
    if (response.data.success) {
      return response.data.resultEmployeeDesignations;
    }
    // if not successful, you probably want to throw an error:
    throw new Error('Not successful');
  }).catch(function (error) {
    // If this console.log statement isn't necessary,
    // better to leave the catch out entirely
    // and leave error handling to the consumer
    console.log("designation err " + error);
    throw error;
  });

Then, in the consuming module, call the function when using it with Promise.all:

const results = await Promise.all([
  loadDesignationTypes(),
  // etc
CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • On point and insightful. Will mark as correct after trying it out. Thanks – hdk Oct 12 '18 at 05:41
  • What if I want to export a promise wrapper for something that does not have promises in built? Shouldn't I use new Promise()? – hdk Oct 12 '18 at 05:52
  • Yes, certainly. If you have something that's asynchronous and callback-based, and you want to use `Promises` (which you should), then you'll have to explicitly construct a `Promise`. But, if you're working with something that already creates and returns a `Promise`, you should use that `Promise` chain rather than creating another one. – CertainPerformance Oct 12 '18 at 05:54
  • Just curious, when explicitly creating and exporting a Promise for asynchronous (callback-based) task , will that cause to run it even it is not called like in my example? – hdk Oct 12 '18 at 06:19
  • If you declare just a `Promise`, then yes, that `Promise`'s code will run immediately, like in your code. If you want to create the `Promise` on demand, then create it inside a function instead, like in the answer. Eg `const fn = () => new Promise((resolve, reject) => { /* do stuff */` – CertainPerformance Oct 12 '18 at 06:24