Monday, 3 April 2017

Nested promises while using Array.map, using Promise.all but still not working

I've been banging my head against a wall for some time now. I have some node code that pulls a bunch of googlecalendar events and then maps these onto a different object structure for use in my webapp... As part of this I need to match the users in the google calendar event with the users in my webapp's database. Here's the code:

router.post('/getCalendar', function(req,res) {  
  // authentication
  var oauth2Client = getOAuthClient();
  var session = req.session;
  oauth2Client.setCredentials({
    access_token: req.user.google.token,
    refresh_token: req.user.google.refreshToken,
    expiry_date: true
  })

  var p = new Promise(function (resolve, reject) {
    // get the next 20 calendar events   
    var calendar = google.calendar('v3');
      calendar.events.list({
        auth: oauth2Client,
        calendarId: 'primary',
        timeMin: (new Date()).toISOString(),
        maxResults: 20,
        singleEvents: true,
        orderBy: 'startTime'
      }, function(err, response) {
        if (err) console.log('err',err)
          // displays all the events
        if (response) console.log('response',response)
        if(response) {
          var events = response.items;
          resolve(events || err);  
        }        
    });

  }).then(function (data) {

    var newdata = data.map(function(item) {
      // create the new object structure and populate with some details
      newObj = {
          _id: item.id,
          _title: item.summary,
          group: [req.headers.group],
          fields: [],
          assignedTo: [],
          google: "calendar",
          googledata: item,
          _category: []
      }

      var extendedFields = {}

      // get the list of attendees
      attendees = item.attendees.map(function(user) {
        var attendee = user.email;
        return attendee;
      })

      // pulls the user information for each attendee using promises
      var promises = attendees.map(function(email) {
        return new Promise(function(resolve, reject) {

          // data is in a mongodb, using mongoose
          User.findOne({'google.email': email}).exec(function (err, user) {
            if (err) return resolve(null);
            resolve(user); //not using reject at all so the Promise.all shouldn't fail
          });
        })
      })

      Promise.all(promises)
        .then(function(value) {
          value.forEach(function(user) {
            if(promise !== null) {
              newObj.assignedTo.push(user);  
            }
          });

          return newObj

      }).catch((error) => {console.log(error)})

  })

  res.json(newdata)
  })

});

I am using Promise.all to wait till all the promises have resolved, but it seems to move onto the next item in the data array before completing the first. Any guidance would be welcome. Please let me know if more details are required.

Thank you.



via Andre Ling

No comments:

Post a Comment