Monday, April 27, 2020

Javascript Promise.all : Way to perform action when Multiple Parallel enqueued Actions are Completed in Lightning Components

As we all know that all actions from Lightning components are sent to server in asynchronous manner and we can not predict the sequence about response from server.

If we have requirement to wait for all operations to complete and then perform some action on lightning components like hiding the spinner or displaying all data at once.

We can either queue the first server call and when we get response then we perform second server call. For this you can use Javascript Promise pattern to sequence the server call. Please refer below URL for complete understanding of sequencing of server call using javascript promise.

JavaScript Promises vs Callback Functions in Lightning Components

Now if we need to fire server calls in parallel and want to wait for all response, then you can utilize promise.all methods to achieve this. This will execute many promises in parallel and wait until all of them are ready. Below is syntax to use promise.all:
 
//create array of promise and pass it to promise.all 
var promiseArray =[promise1, promise2];
var combinedPromise = Promise.all(promiseArray);
//this return single promise. Now handle it with then and catch
combinedPromise
.then($A.getCallback(function(results){
 //handle success
 var promise1Results = results[0]; //Results from Promise 1
 var promise2Results = results[1]; //Results from Promise 2
})) 
.catch($A.getCallback(function () { 
 //Handle errors on any promise here
 console.log('Some error has occured'); 
}));

Note:
  • Promise.all takes an array of promises and returns a new promise.
  • The new promise resolves when all listed promises are settled, and the array of their results becomes its result.
  • Order of the resulting array members is the same as in its source promises. Even though the first promise takes the longest time to resolve, it’s still first in the array of results.
  • If any of the promises is rejected, the promise returned by Promise.all immediately rejects with that error.
  • For example, if there are multiple fetch calls and one fails, the others will still continue to execute, but Promise.all won’t watch them anymore. They will probably settle, but their results will be ignored. Promise.all does nothing to cancel them, as there’s no concept of “cancellation” in promises.
  • This will help to improve the performance of lightning components as server operations are not performed in sequential order. Due to parallel call to server, lightning components will perform better.
I have created a sample lightning component which fetch Account and Task records from server and displays it in UI only when both operations are completed and response is returned to lightning components. below is gif image displaying the lightning component functionality:


Below is complete snippet for your reference:

Hope this will help!!

Friday, April 17, 2020

Get the Content (Blob) of File from Box and Store/Manipulate it in Salesforce

Through this blog, I am going to share sample apex script through which you can get content of file from box as blob and then store or manipulate it within salesforce.

I have already written a blog to explain how to get box access token (needed for handshake with Box) and to display file content in salesforce in VF page without storing it in salesforce. You can cosider it as Mashup inSalesforce. Please refer below URL to that:

Box and Salesforce Integration

In order to get box file content, we need to have box file Id and box access token.

Box does not provide direct API to get file content. First you need to do callout to get download URL and then you perform another API callout to get file content. Also you perform another API call to get file details like filename in order to store it in salesforce.

I am going to store box file in salesforce library for demo purpose. You can store it as attachments or read the content on the fly to perform some logic instead of saving it.

Add below URLs in remote site settings before performing the callouts:
  • https://api.box.com
  • https://dl.boxcloud.com 

Below is required code and it is self explainatory as comments are mentioned for each methods:

Now run below script in developer console:

string boxFileId='6542xxx28604';
string access_token='0xxxxxxxxxxxxxxxxxxxxxxxxxxxredx0P';
string sfdcLibraryName='Box_File_Library';
string boxFilename= SK_BoxAPIUtilityClass.findFileNameFromBox(boxFileId,access_token);
system.debug('****boxFilename:'+boxFilename);
SK_BoxAPIUtilityClass.readFileContentFromBox(boxFileId,boxFilename,sfdcLibraryName,access_token);



Use Case

During sandbox refresh, all custom settings data gets refreshed from production values. So before refresh, you have to take back up each custom settings data and after refresh, you need to update the custom setting records. In order to automate this, you can write script through which you can push all custom setting data to box folder. Code to upload the files from Salesforce to box is already shared in blog  Box and Salesforce Integration.

Now we need to get the content of all csv files stored in box and update the custom setting in salesforce. Once you get the content of file, you can parse csv file and update custom settings.

Hope this helps!!!


Saturday, April 11, 2020

JavaScript Promises vs Callback Functions in Lightning Components

As we all know that all server calls from lightning components are asynchronous in nature. If we call 2 different apex methods from lightning components, then there is no surety that which will return response first. In order to provide sequencing between these 2 calls, we have to write second method call in callback function of first apex call as mentioned below:

findDataUsingNormalCall : function(component, event, helper) {
  var actionName1= component.get("c.findMyAccounts");
  var params1={"numberOfRecords":2};
  actionName1.setParams(params1);
  actionName1.setCallback(this, function(response) {
    var state = response.getState();
    if (state === "SUCCESS") {
        var apexResponse1=response.getReturnValue();
        component.set("v.ltngAccList",apexResponse1);
       //Now perform second Call
        var actionName2= component.get("c.findMyPendingTasks");
        var params2={"numberOfRecords":2};
        actionName2.setParams(params2);
        actionName2.setCallback(this, function(response) {
           state = response.getState();
           if (state === "SUCCESS") {
              var apexResponse2=response.getReturnValue();
              component.set("v.ltngTaskList",apexResponse2);
           }else if(state === "ERROR"){
              var errors2 = response.getError();
              console.error(errors2);
           }
        });
        $A.enqueueAction(actionName2);
     }else if(state === "ERROR"){
        var errors1 = response.getError();
        console.error(errors1);
     }
  });
  $A.enqueueAction(actionName1);

Now if you have to perform multiple server side apex calls from lightning components in sequential order, code becomes very difficult to understand and read and difficult to maintain this kind of code.

Javascript Promises

Promise pattern is very common in javascript to handle asynchronous operations.  Prior to promises events and callback functions were used but they had limited functionalities and created unmanageable code.

Promise can have 3 states:
  • Pending
  • Fulfilled
  • Rejected
Use below syntax to create promise:

var promise1 = new Promise($A.getCallback(function(resolve, reject){
     //perform logic like server call
     if (/* success */) {  
        resolve("result");
     }else {
        reject("error");
     }
}));
  • Constructor takes only one argument as a function. 
  • Callback function takes two arguments, resolve and reject
  • Perform operations inside the callback function and if everything went well then call resolve.
  • If desired operations do not go well then call reject.
In order to consume promise, use .then or .catch methods as shown below:

promise1 . 
    .then($A.getCallback(function(result){
             //handle success
 }), 
 $A.getCallback(function(error){
            //handle error
        })
     ) 
    .catch($A.getCallback(function () { 
        console.log('Some error has occured'); 
    }));

Remember:
  1. then() method automatically invoked when promise is either resolved (fulfilled) or reject.
  2. then() method takes 2 functions as parameters:
    • If promise is resolved and a result is received, First function is executed.
    • If promise is rejected and an error is received, Second function is executed(optional).
  3. catch() method is invoked when a promise is either rejected or some error has occurred in execution. catch take 1 function as parameter. If you are using the second parameters for then function then use catch for error handling.
Calling multiple asynchronous functions and Chaining them using Promises

You can use below pattern in order to perform different asynchronous operation in synchronous manner.

new Promise($A.getCallback(function(resolve, reject){}))
    .then(
        // resolve handler
        $A.getCallback(function(result) {
   //when first call is successfull, then create new 
   //instance of promise to make another call
          return new Promise($A.getCallback(function(resolve,reject){}));
        }),
 // reject handler
        $A.getCallback(function(error) {
            console.log("Promise was rejected: ", error);
    //you can create another promise for error handling
        })
    )
    .then(
        // resolve handler
        $A.getCallback(function() {
            //perform logic when second call is successfull
        })
    );
I have created a sample lightning component which explain the functionality of callback function and promise pattern. Below are details about this component functionality:
  • Component contains 2 button which invoke 2 different apex methods by using callback pattern and promise pattern.
  • When user clicks on "Fetch 2 records using callback pattern" button, system fires 2 server calls to get account and task records in asynchronous manner. So records will get displayed on UI based on response from server. There will be no sequencing of these 2 method invocation.
  • When user clicks on "Fetch 3 records using promise pattern", system first fire an asynchronous call to get account records and once account data is recieved, then it will fire another asynchronous call to get task records. This functionality uses promise pattern to fire 2 asynchronous call in synchronous manner. 


Below is code snippet:

Best Practices:
  • Always use catch or reject handler.
  • Always use $A.getCallback() when using promise pattern in lightning components. Even if you do not use this, then sometimes it will work but it will be very difficult to debug if something went wrong. Sometimes if you don't use it, then results may get delayed on UI and can cause performance issues. 
Hope this will help!!