Asynchronous Data Transactions
When working with data stored in NetSuite or, internally, within the application, SCA often needs to perform tasks asynchronously. Handling tasks asynchronously improves the performance of SCA implementations.
To handle tasks asynchronously, SCA 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 jQuery API documentation for information about the methods provided by the Deferred Object API.
Although there are other JavaScript mechanisms for performing tasks asynchronously, NetSuite recommends that you use jQuery Deferred Objects when customizing or extending SCA.
There are two main contexts where SCA uses the Deferred Object API:
-
When performing AJAX calls using the
save()
,fetch()
, anddestroy()
methods of a model or collection -
When performing tasks asynchronously using promises
See the following sections for more information:
Using the Deferred Object in AJAX Calls
SuiteCommerce Advanced (SCA) frequently interacts with data stored in NetSuite. To perform a data transaction, the code within a router or view calls a method on the frontend 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 accepts a single function as an argument. This function calls the showContent()
method of the view and performs other tasks, which defers calling the showContent()
method until the data transaction initiated by the save method is completed.
Using Promises in Asynchronous Data Transfers
SuiteCommerce Advanced (SCA) 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 (SCA) includes an AjaxRequestsKiller utility module that you can use to stop execution of AJAX requests. You can enhance performance 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
andmodel.fetch
methods. In such cases, you should pass thekillerID
property to the method as shown in the following example:model.fetch({ killerId: AjaxRequestsKiller.getKillerId() })
-
Site Search: The SiteSearch module uses the AjaxRequestsKiller module to delete unnecessary AJAX calls when using 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 by deleting old requests.
When the value of the killerID
property is reset, this module abandons 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 tasks:-
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
-