Considering following code I have following questions:
#1 The values returned by those bluebird.all functions need to be accessible in the later functions. From what I've read I could also use the this-context, without the necessity to declare the variables before. But I got some issues accessing those values in nested functions.
#2 Is spread the way to go in order to make those parameters accessible in subsequent functions?
#3 Since those functions are only working within the main method, should they be nested like this?
#4 I could not find any nicer solutions for conditional promise-chain execution. I'd prefer a less verbose solution, if there is any.
#5 As #3, but this time nested within nested function.
function create(contactRequestPayload) {
// #1 Local variables vs this
var
contactRequest = {},
property = {};
return bluebird.all([
new ContactRequestModel(contactRequestPayload).save(),
getPropertyById(contactRequestPayload.propertyId),
sendContactMail()
])
// #2 Correct usage of spread
.spread(function (_contactRequest, _property) {
contactRequest = _contactRequest;
property = _property;
})
.then(processFeedbackEmail)
.then(updateModelState)
.then(returnContactRequest)
.catch(errorHandler);
// #3 Nested functions
function processFeedbackEmail() {
// #4 Conditional code execution
if (!_.get(property, "contact.email.feedback")) {
return bluebird.resolve();
}
return createFeedbackObject()
.then(convertToXml)
.then(sendFeedbackMail)
.catch(function (error) {
logger.warn(error);
});
// #5 Nested functions within a nested function
function createFeedbackObject() {
return contactRequestFeedbackObjectService.from(property, contactRequest);
}
function convertToXml(contactFeedbackObject) {
contactRequest.feedbackJson = contactFeedbackObject;
return objectToXmlService.convert(contactFeedbackObject);
}
function sendFeedbackMail(contactFeedbackXml) {
contactRequest.feedbackXml = contactFeedbackXml;
return contactRequestFeedbackMailService.send(property.contact.email.feedback, contactFeedbackXml);
}
}
function returnContactRequest() {
return contactRequest;
}
function sendContactMail() {
return searchServiceClient.sendContactMail(contactRequestPayload);
}
function getPropertyById(propertyId) {
return getPropertyServiceClient().fetchPropertyById(propertyId);
}
function updateModelState() {
contactRequest.state = 'SENT';
return contactRequest.save();
}
}
Promise-chains let us sequence things as we would synchronous code, in a forward flow. I find that inlining functions regains important context. To use a previous variable, I use good old indentation:
function create(contactRequestPayload) {
return bluebird.all([
new ContactRequestModel(contactRequestPayload).save(),
getPropertyServiceClient().fetchPropertyById(contactRequestPayload.propertyId),
searchServiceClient.sendContactMail(contactRequestPayload)
])
.spread(function processFeedbackEmail(contactRequest, property) {
if (_.get(property, "contact.email.feedback")) {
return contactRequestFeedbackObjectService.from(property, contactRequest)
.then(function convertToXml(feedback) {
contactRequest.feedbackJson = feedback;
return objectToXmlService.convert(feedback);
})
.then(function sendFeedbackMail(xml) {
contactRequest.feedbackXml = xml;
return CRFeedbackMailService.send(property.contact.email.feedback, xml);
})
.catch(function (error) {
logger.warn(error);
});
}
})
.then(function updateModelState() {
contactRequest.state = 'SENT';
return contactRequest.save();
})
.then(function returnContactRequest() {
return contactRequest;
})
.catch(errorHandler);
}
(The function names are optional of course, but I kept them for reference.)
For the condition, I inverted it since returning undefined
equals bluebird.resolve()
.
Some might argue this is a question of style, but ES7 takes this analogy to its natural conclusion:
async function create(contactRequestPayload) {
var [ contactRequest, property ] = await Promise.all([
new ContactRequestModel(contactRequestPayload).save(),
getPropertyServiceClient().fetchPropertyById(contactRequestPayload.propertyId),
searchServiceClient.sendContactMail(contactRequestPayload)
]);
if (_.get(property, "contact.email.feedback")) {
try {
var feedback = await contactRequestFeedbackObjectService.from(property,
contactRequest);
contactRequest.feedbackJson = feedback;
contactRequest.feedbackXml = await objectToXmlService.convert(feedback);
await CRFeedbackMailService.send(property.contact.email.feedback, xml);
} catch (error) {
logger.warn(error);
}
}
contactRequest.state = 'SENT';
await contactRequest.save();
return contactRequest;
}
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.