Asynchronous Data Transactions

This topic applies to

Applies to

SuiteCommerce Advanced

When working with data stored in NetSuite or internally within the application, SuiteCommerce Advance often needs to perform tasks asynchronously. Handling tasks asynchronously improves the performance and user experience of SuiteCommerce Advanced.

To handle tasks asynchronously, SuiteCommerce Advanced uses the jQuery Deferred Object API. This API provides an easy way of registering callbacks and monitoring the success or failure of data transactions. See https://api.jquery.com/category/deferred-object/ for information on the methods provided by the Deferred Object API.

Note

Although there are other mechanisms JavaScript for performing tasks asynchronously, NetSuite recommends that you use jQuery Deferred Objects when customizing or extending SuiteCommerce Advanced.


There are two main contexts where SuiteCommerce Advanced uses the Deferred Object API:

  • When performing AJAX calls when using the save(), fetch(), and destroy() methods of a model or collection.

  • When performing tasks asynchronously using promises

Using the Deferred Object in AJAX Calls

SuiteCommerce Advanced frequently interacts with data stored in NetSuite. To perform a data transaction, code within a Router or View calls a method on the front-end model. This method then makes an AJAX call that sends an HTTP request to the service.

In general, this AJAX call needs to be asynchronous since other application code may need to continue processing while the data is loading. The primary reason for using asynchronous AJAX calls is that each browser window operates within a single thread. A synchronous AJAX call will freeze the browser until the AJAX call is complete.

One frequent use of the deferred object is to wait until the AJAX call is complete to perform other tasks.

The following example from Case.Detail.View shows how the done method is used when saving data to NetSuite:

this.model.save().done(function()
{
    self.showContent();
    self.showConfirmationMessage(_('Case successfully closed').translate());
    jQuery('#reply').val('');
});

In this example, the done method accepcts a single function as an argument. This function calls the showContent() method of the view and performs other tasks. This defers calling the showContent() method until the data transaction initiated by the save method is completed.

Using Promises in Asynchronous Data Transfers

SuiteCommerce Advanced also uses the Deferred Object API in other contexts where tasks need to be performed asynchronously. In this case, a module explicitly creates an instance of the jQuery.Deferred object. After creating this object the module must ensure that the deferred object is ultimately resolved. This resolution is handled using promises.

Promises are part of the jQuery Deferred Object that enable asynchronous data transfers. Promises prevent other methods from interfering with the progress or status of the request. The following code example from the the ProductList.CartSaveForLater.View module shows how a deferred object is created and ultimately resolved:

addItemToList: function (product)
      {
         var defer = jQuery.Deferred();

         if (this.validateGiftCertificate(product))
         {
            var self = this;


            this.application.ProductListModule.Utils.getSavedForLaterProductList().done(function(pl_json)
            {
               if (!pl_json.internalid)
               {
                  var pl_model = new ProductListModel(pl_json);

                  pl_model.save().done(function (pl_json)
                  {
                     self.doAddItemToList(pl_json.internalid, product, defer);
                  });
               }
               else
               {
                  self.doAddItemToList(pl_json.internalid, product, defer);
               }
            });
         }
         else
         {
            defer.resolve();
         }

         return defer.promise();
      }

Stopping AJAX Requests

SuiteCommerce Advanced includes an AjaxRequestsKiller utility module used to stop execution of AJAX requests. Performance is enhanced by stopping AJAX requests that are no longer needed. This module is primarily used in two contexts:

  • URL changes: When a URL change is detected, this module stops execution of all pending AJAX requests that were initiated by another Router or View. Some AJAX requests are initiated without a URL change, for example, the collection.fetch and model.fetch methods. In such cases, you should pass the killerID property to the method as in the following:

    model.fetch({
       killerId: AjaxRequestsKiller.getKillerId()
    })
  • Site Search: The SiteSearch module uses the AjaxRequestsKiller module to delete unnecessary AJAX calls when using the type ahead functionality. As a user enters a character in the search field, the SiteSearch module sends an AJAX request to retrieve information from the Item Search API. As the user continues entering characters, additional AJAX requests are sent. Using the AjaxRequestsKiller improves performance be deleting old requests.

When the value of the killerID property is reset, this module aborts the AJAX request associated with the old value of the killerID property. It also sets the preventDefault property of the request to true to avoid sending an error to the ErrorHandling module.

This module defines the following properties and methods:

  • getKillerId (method): returns an unique ID that identifies the AJAX request. Each time the URL is reset, a new ID is generated.

  • getLambsToBeKilled (method): returns an array of AJAX request IDs to be halted.

  • mountToApp (method): loads the module into the application context. This method performs the following

    • Sets the value of the killerID property.

    • Pushes the killerID property to an array.

    • When the killerID property is reset, calls the abort method on the AJAX request.

Related Topics