Search code examples
javascriptnode.jsgoogle-classroom

Block code until first forEach loop finishes to use result in another forEach loop in Node


There are similar questions like this one here in stackoverflow, but I can't find one that resolves this in particular. I have two forEach loops in Node and one (this one: s.forEach((su) => { cw1.push(su.courseWorkId); }); ) uses the results of the previous one to do its iteration, but it fires asynchronously before the first one finishes so it always tells me that "const s" (the result of the first forEach loop) is empty. Everything else in the code works fine. Any help would be appreciated.

const fs = require('fs');
const path = require('path');
const {google} = require('googleapis');
const keys = require("./file.json");
const sc = require('./jwt.js');
const scopes = sc.scopes;

const j2 = new google.auth.JWT(keys.client_email,null,keys.private_key,scopes,'me@email.com');

const classroom = google.classroom({version: 'v1', auth:j2});
const cl = classroom.courses;

let cl1 =  ['34809075556', '34800434710'];
let cw1 = [];

function getwi(){
  cl1.forEach((ids) => {                                                   
    cl.courseWork.list({courseId:ids}, (e,r) => {
      const s = r.data.courseWork;
      s.forEach((su) => { cw1.push(su.courseWorkId); });
    });
  });
}

getwi(); 

Solution

  • Modifying a global variable asynchronously is generally a bad idea. Instead wrap the asynchronous task into a promise, then resolve that promise to the value you need.

      const getCourseWork = courseId => new Promise((resolve, reject) => cl.courseWork.list({ courseId, }, (err, result) => err ? reject(err) : resolve(result)));
    

    Then you can get the result as:

      Promise.all( cl1.map(getCourseWork) )
         .then(result => console.log("The result is:", result.flat().map(it => it.id)))
         .catch(error => console.error("An error occured:", error));
    

    That way, all the calls are done in parallel, and are thus faster as doing one after another.

    Read on