2

I have this code

export const callingEveSkill = () => (dispatch, getState) => {

  fetch('https://esi.tech.ccp.is/latest/characters/' + getState().ViewChr.Cid + '/skills/?datasource=tranquility&token=' + getState().ViewChr.At)
    .then(response => response.json())
    .then(json => {

         var SkillList = ( json.skills.map((item, i) => {
             var skill = TypeIdToName(item.skill_id)
            return  {
                skill_id: (skill) ,
                current_skill_level: item.current_skill_level,
                skillpoints_in_skill: item.skillpoints_in_skill
            }

           }))

        return SkillList

    })
    .then( SkillList => {

        dispatch(updateSk( SkillList))
        dispatch(updateSkL('true'))

    })
    .catch(err => {
        console.log("skill error:" + err)
    });
}

In side the code i call TypeIdToName to call a 3rd party api to change the skill id to readable text. I see the calls going out and that it returns the readable name but the SkillList show as undefined.

1 Answers1

1

The problem here is that .map() won't wait for Promises to fulfil. here are few thoughts on how to get around that using Promises composing:

1) !IMPORTANT Refactor your API call TypeIdToName() so it returns a Promise

See this for more info: How do I convert an existing callback API to promises?

2) Install Q or any other library that allows Promises combination. (Promise.all might also work for you depending on your env)

https://github.com/kriskowal/q

OR

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

3) When mapping API calls - collect the promises they return.

4) Use Q.all() to return a Promise that will only be fulfilled when all the API calls are done. You might want to limit your pull of simultaneus connections at some point.

So your code would look like this:

import Q from 'q';

export const callingEveSkill = () => (dispatch, getState) => {

  fetch('https://esi.tech.ccp.is/latest/characters/' + 
                              getState().ViewChr.Cid + 
            '/skills/?datasource=tranquility&token=' + 
             getState().ViewChr.At
    )
    .then(response => response.json())
    .then(json => {

      //We build the array of promises here
      let promises = json.skills.map((item, i) => {

        //If you did the Step 1 - this should return a Promise object
        //So our .map() has something to work with
        return TypeIdToName(item.skill_id).then(
          (skill) => {
            //As promises fulfil - the array of promises 
            //turns into array of objects like this one
            return {
              skill_id: (skill),
              current_skill_level: item.current_skill_level,
              skillpoints_in_skill: item.skillpoints_in_skill
            }
          }
        );

      })

      //And this promises fulfils when all the others do
      return Q.all(promises);

    })

    //So here we get a SkillList
    .then(SkillList => {

      dispatch(updateSk(SkillList))
      dispatch(updateSkL('true'))

    })
    .catch(err => {
      console.log("skill error:" + err)
    });
}
Stas Parshin
  • 1,458
  • 1
  • 16
  • 21