Reputation: 2386
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:
getPosition
and getCommittees
and is supposed to call formatJSON as soon as getPosition() and getCommittees() finish executing and return the formatted JSON DataThe 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!
Upvotes: 3
Views: 266
Reputation: 10396
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));
Upvotes: 2