Making parallel async await calls in ReactJS

Viewed 1441

Currently each of the value is set after setting the previous value, the async calls are not executed in parrallel. How do I make these calls execute in parallel?

  const [index, setIndex] = useState(0);
  const [roll, setRollNo] = useState(1);
  const [sem, setSemester] = useState(1);

  useEffect(() => {
    getMyValue();
  }, []);

  const getMyValue = async () => {
    try {
      setIndex(JSON.parse(await AsyncStorage.getItem('@branch')) || 0);
      setSemester(JSON.parse(await AsyncStorage.getItem('@sem')) || 1);
      setRollNo(JSON.parse(await AsyncStorage.getItem('@roll')) || 1);
    } catch (e) {
      //  console.log(e);
    }
  };
5 Answers

You can use Promise.all

const [index, semester, roll] = await Promise.all([
AsyncStorage.getItem('@branch'),
AsyncStorage.getItem('@sem'),
AsyncStorage.getItem('@roll')]);

setIndex(JSON.parse(index) || 0);
setSemester(JSON.parse(semester) || 1);
setRollNo(JSON.parse(roll) || 1);

Or if you like to turn such thing into mapping monstrosity as recommended in the answers there you go...

const params = ['@branch', '@sem', '@roll'];
const defaultValues = [0, 1, 1];

const [index, semester, roll] = await Promise.all(
  params.map(AsyncStorage.getItem))
  .then((values) => values.map((pr, index) => JSON.parse(pr) || defaultValues[index]));

setIndex(index);
setSemester(semester);
setRollNo(roll);

To execute several promises in parallel you need organize them as array and execute unsing Promise.all:

  const [index, setIndex] = useState(0);
  const [roll, setRollNo] = useState(1);
  const [sem, setSemester] = useState(1);

  useEffect(() => {
    getMyValue();
  }, []);

  const getMyValue = async () => {
    try {
      const itemsArr = ['@branch', '@sem', '@roll']
      const result = await Promise.all(promisesArr.map(item => AsyncStorage.getItem(item)))
      setIndex(JSON.parse(result[0]) || 0);
      setSemester(JSON.parse(result[1]) || 1);
      setRollNo(JSON.parse(result[2]) || 1);
    } catch (e) {
      //  console.log(e);
    }
  };

Using for await of ...

We use an array of jobs to getItem, then after await, we can set the state of each item based on its type.

@Jozef's answer is also a great option as well, very good use of array deconstruction there

const response = []

const jobs = ["@branch", "@sem", "@roll"]

for await (item of jobs) {
  const res = await AsyncStorage.getItem(item);
  response.push({
    type: item, 
    res
  })
}

/**
 response 
 [ 
  { type: "@branch", res: <res> }, 
  { type: "@sem", res: <res> }, 
  { type: "@roll", res: <res> }] 
*/ 


response.forEach(item => {
  const { type, res } = item;
  if (type === "@branch") {
    setIndex(JSON.parse(res))
  } else if (type === "@semester") {
    setSemester(JSON.parse(res))
  } else if (type === "@roll") {
    setRollNo(JSON.parse(res))
  }
})

you don't need a async await here as you don't want to wait just use a promise instead

const getMyValue2 = () => {
    try {
      Promise.all([
        Promise.resolve( AsyncStorage.getItem('@branch')),
        Promise.resolve( AsyncStorage.getItem('@sem')),
        Promise.resolve( AsyncStorage.getItem('@roll'))
      ]).then(data => {
        setIndex(JSON.parse(data[0] || 0));
        setRollNo(JSON.parse(data[1] || 1));
        setSemester(JSON.parse(data[2] || 1));
      });
    } catch (e) {
      //  console.log(e);
    }
  };
Related