简体   繁体   中英

ES6 - Promise.all within a Promise.resolve

I'm using ecmascript 6 and am trying to execute a Promise.all() within a Promise.resolve() together in my API.

Here's my code:

import jwt from "jsonwebtoken";
import Database from "../../../util/Database";
import send from "../../../util/send";

var updatePosition = function(organizationId, positionId, positionTitle) {
  let updatedPosition = {
    organization_id: organizationId,
    title: positionTitle
  };
  return Database.connection.query('UPDATE positions SET ? WHERE id=?', [updatedPosition, positionId]);
}

var unLinkUserToPosition = function(positionId) {
  return Database.connection.query('UPDATE users SET position_id=NULL WHERE position_id=?', positionId);
}

var linkUserToPosition = function(positionId, userId) {
  return Database.connection.query('UPDATE users SET position_id=? WHERE id=?', [positionId, userId]);
}

var getPositionAndCommittees = function(positionId) {
  return Promise.all([getPosition(positionId), getCommittees(positionId)]).then(formatJSON);
}

var getPosition = function(positionId) {
  return Database.connection.query('SELECT \
    p.id as position_id, \
    p.title as position_title, \
    u.id as user_id, \
    u.facebook_UID, \
    u.email, \
    u.first_name, \
    u.last_name, \
    u.phone, \
    u.semester_joined, \
    u.year_joined, \
    u.thumbnail_photo_URL, \
    u.cover_photo_URL \
    FROM positions p \
    LEFT JOIN users u ON p.id=u.position_id \
    WHERE p.id=? \
    ORDER BY p.id ASC', positionId);
}

var getCommittees = function(positionId) {
  return Database.connection.query('SELECT \
    c.id as committee_id, \
    c.title as committee_title, \
    u.id as chairmen_user_id, \
    u.thumbnail_photo_URL as chairmen_thumbnail_photo_URL, \
    u.first_name as chairmen_user_first_name, \
    u.last_name as chairmen_user_last_name \
    FROM committees c \
    LEFT JOIN users u ON c.chairmen_id=u.id \
    WHERE c.position_id=? ORDER BY c.title ASC', positionId);
}

var formatJSON = function(results) {
  let positionResult = results[0][0];
  let committeesResult = results[1];
  let position = {
    id: positionResult.position_id,
    title: positionResult.position_title,
    user: {
      id: positionResult.user_id,
      facebookUID: positionResult.facebook_UID,
      email: positionResult.email,
      firstName: positionResult.first_name,
      lastName: positionResult.last_name,
      phone: positionResult.phone,
      semesterJoined: positionResult.semester_joined,
      yearJoined: positionResult.year_joined,
      thumbnailPhotoURL: positionResult.thumbnail_photo_URL,
      coverphotoURL: positionResult.cover_photo_URL
    },
    committees: committeesResult
  };

  return position;
}

module.exports = function(req, res) {
  let token = req.headers['bearer-authorization'];
  let tokenSecret = ENV.API_SECRET
  let decodedToken = jwt.verify(token, tokenSecret);

  let organizationId = 1
  let positionId = req.params.positionId;
  let positionTitle = req.body.title;
  let positionUserId = req.body.userId;

  Promise.resolve(updatePosition(organizationId, positionId, positionTitle))
    .then(unLinkUserToPosition(positionId))
    .then(linkUserToPosition(positionId, positionUserId))
    .then(getPositionAndCommittees(positionId))
    .then(send.success(res))
    .catch(send.failure(res));
};

Side Note: I'm using promise-mysql for my database queries, which means that when I return Database.connection.query() , it's actually returning a new Promise


Here's what the send.success and send.failure functions look like:

var send = {
  success: function(response) {
    return function(data) {
      response.status(200).json(data);
    };
  },
  failure: function(response) {
    return function(error) {
      var statusCode = error.statusCode || 500;

      if (statusCode === TEMPORARY_REDIRECT && error.body && error.body.value) {
          response.status(200).json(error.body.value);
          return;
      }

      console.error(error.stack);

      response.status(statusCode).json({
        message: error.message
      });
    };
  }
}

Heres the order I'm trying to get my functions to execute:

  1. updatePosition
  2. unLinkUserToPosition
  3. linkUserToPosition
  4. getPositionAndCommittees - This function calls Promise.all with getPosition and getCommittees and is supposed to call formatJSON as soon as getPosition() and getCommittees() finish executing and return the formatted JSON Data
  5. send.success - This just outputs the JSON that should be returned from formatJSON

The way it's executing right now is that the data returned from linkUserToPosition is being returned as the data in the send.success function, which means that the Promise.resolve is not waiting for getPositionAndCommittees to finish executing the Promise.all .

Here's what the output looks like:

{
  "fieldCount": 0,
  "affectedRows": 1,
  "insertId": 0,
  "serverStatus": 2,
  "warningCount": 0,
  "message": "(Rows matched: 1  Changed: 0  Warnings: 0",
  "protocol41": true,
  "changedRows": 0
}

Any suggestions on how I can accomplish what I'm trying to do would be greatly appreciated!

I think the problem is that several functions are immediatly started and not only after the previous steps completed.

Assuming this call chain:

updatePosition(organizationId, positionId, positionTitle)
.then(unLinkUserToPosition(positionId))
.then(linkUserToPosition(positionId, positionUserId))
.then(getPositionAndCommittees(positionId))
.then(send.success(res))
.catch(send.failure(res));

This means the asynchronous functions updatePosition , unLinkUserToPosition , linkUserToPosition and getPositionAndCommittees will all be immediately started. The send functions too, but as these return a function which will be executed later it's no problem. This means the functions execute immediatley and the resulting promise is assigned to .then() of the previous function - which makes no sense because then accepts a function (that might return a promise), and not a promise. What you need is:

updatePosition(organizationId, positionId, positionTitle)
.then(updatePositionResult => unLinkUserToPosition(positionId))
.then(unLinkUserToPositionResult => linkUserToPosition(positionId, positionUserId))
.then(linkUserToPositionResult => getPositionAndCommittees(positionId))
.then(send.success(res))
.catch(send.failure(res));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM