How to make code which uses Lightning promises look more synchronous
You have two basic problems. First, you don't need $A.getCallback unless you need to call component.set. At all other points, it's superfluous.
main: function(component, helper) {
helper.promise1(component, helper).then(
function(record) {
return helper.promise2(component, helper, record).then(
function(){
console.log("Success");
helper.showToastMessage(component, "Great Success!!!!")
},
function(errorMessage){
console.log("Rejected by second promise2");
helper.showToastMessage(component, "Failure " + errorMessage);
}
)
},
function(errors){
console.log("Rejected by first promise1");
let message = errors && Array.isArray(errors) && errors.length > 0 ? errors[0].message :'Unknown error';
helper.showToastMessage(component, "Failure " + message);
}
)
}
Next, you typically chain a then from the previous then:
main: function(component, helper) {
helper.promise1(component, helper).then(
function(record) {
return helper.promise2(component, helper, record);
},
function(errors){
console.log("Rejected by first promise1");
let message = errors && Array.isArray(errors) && errors.length > 0 ? errors[0].message :'Unknown error';
helper.showToastMessage(component, "Failure " + message);
}
).then(
function(){
console.log("Success");
helper.showToastMessage(component, "Great Success!!!!")
},
function(errorMessage){
console.log("Rejected by second promise2");
helper.showToastMessage(component, "Failure " + errorMessage);
}
)
}
Also, you typically want to use catch instead of the two-parameter then version, which lets you have as single error handler:
main: function(component, helper) {
helper.promise1(component, helper).then(
function(record) {
return helper.promise2(component, helper, record);
}
).then(
function(){
console.log("Success");
helper.showToastMessage(component, "Great Success!!!!")
}
).catch(
function(errorMessage){
console.log("Error occuring during chain");
helper.showToastMessage(component, "Failure " + errorMessage);
}
);
}
As a bonus, arrow functions makes things a bit more legible:
main: function(component, helper) {
helper.promise1(component, helper).then(
record => helper.promise2(component, helper, record);
).then(
() => {
console.log("Success");
helper.showToastMessage(component, "Great Success!!!!")
}
).catch(
(errorMessage) => {
console.log("Error occuring during chain");
helper.showToastMessage(component, "Failure " + errorMessage);
}
);
}
After that, you might want to remove the debug logs for production use:
main: function(component, helper) {
helper.promise1(component, helper).then(
record => helper.promise2(component, helper, record)
).then(
() => helper.showToastMessage(component, "Great Success!!!!")
).catch(
errorMessage => helper.showToastMessage(component, "Failure " + errorMessage)
);
}
This is what you'd typically see in production-ready code (plus comments, as necessary).
Looks like I have found some possible solution to beautify this code.
main: function(component, helper) {
helper.promise1(component, helper).then(
$A.getCallback(helper.promise2),
$A.getCallback(function(errors){
console.log("Rejected by first promise1");
let message = errors && Array.isArray(errors) && errors.length > 0 ? errors[0].message :'Unknown error';
helper.showToastMessage(component, "Failure " + message);
})
).then(
$A.getCallback(function(){
console.log("Success");
helper.showToastMessage(component, "Great Success!!!!")
}),
$A.getCallback(function(errorMessage){
console.log("Rejected by second promise2");
helper.showToastMessage(component, "Failure " + errorMessage);
})
)
}
However, if we need component
and helper
variables in the second promise then we have to tweak resolve
statement and change it from
resolve(record)
to
resolve({'c':component, 'h':helper, 'r':record})
and to tweak the second promise from
sendMessagePromise : function(component, helper, record) {
...
to
sendMessagePromise : function(value) {
let component = value.c, helper = value.h, record = value.r;
Also using suggestions from sfdcfox I could rewrite this as following:
main: function(component, helper) {
helper.promise1(component, helper).then(
promise2
).then(
() => helper.showToastMessage(component, "Great Success!!!!")
).catch(
errorMessage => helper.showToastMessage(component, "Failure " + errorMessage)
);
}