Promise Object
A promise is a JavaScript object that represents the eventual result of an asynchronous process. After the promise object is created, it serves as a placeholder for the future success or failure of the asynchronous process. While the promise object is waiting, the remaining segments of the script can execute. With promises, you can write asynchronous code that is intuitive and efficient.
A promise holds one of the following values:
-
fulfilled
– The operation is successful. -
rejected
– The operation failed. -
pending
– The operation is still in progress and has not yet been fulfilled or rejected.
When it is first created, a promise holds the value pending
. After the associated process is complete, the value changes to fulfilled
for a successful completion or to rejected
for an unsuccessful completion. A success or failure callback function attached to the promise is called when the process is complete. Note that a promise can only succeed or fail one time. When the value of the promise updates to fulfilled
or rejected
, it cannot change.
SuiteScript 2.x provides promise APIs for selected modules as listed in SuiteScript 2.x Promise APIs. In SuiteScript 2.x, all client scripts support the use of promises. Starting with NetSuite 2021.1, a subset of server scripts also support the use of promises. Custom promises can also be created for client scripts. For an example of creaing a custom promise, see Custom Promises.
When you code your SuiteScript scripts to be asynchronous, you should also consider following best practices. A few best practices are included in Best Practices for Asynchronous Programming with SuiteScript.
For more information about JavaScript promises, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise.
SuiteScript 2.1 Server Scripts and Promises
Starting in NetSuite 2021.1, SuiteScript 2.1 supports non-blocking asynchronous server-side promises expressed using the asnyc
, await
, and promise
keywords. This allows you to upload and deploy a SuiteScript 2.1 script that includes the async
, await
, and promise
keywords. However, these keywords are only valid for a subset of modules:
-
N/http
-
N/https
-
N/llm
-
N/query
-
N/search
-
N/transaction
In SuiteScript 2.1 server scripts, you will receive an error if you use the async
, await
, or promise
keyword in any other module API. In other words, no other modules support the use of the async
, await
, and promise
keywords in server scripts.
When using server-side promises in SuiteScript 2.1, you should consider the following:
-
This capability is not for bulk processing use cases where an out-of-band solution, such as a work queue, may suffice.
-
This capability is mainly for in-process and distinct operations, such as business functions on a list of transactions when ordering does not matter.
For more information about SuiteScript versions and SuiteScript 2.1, see SuiteScript Versioning Guidelines and SuiteScript 2.1.
Best Practices for Asynchronous Programming with SuiteScript
When using promises in your SuiteScript scripts to implement asynchronous programming, you should consider the following best practices. If you are using SuiteScript 2.1 scripts, consider using the async
and await
keywords to implement asynchronous solutions instead of using the promise
keyword.
For additional best practices for SuiteScript scripts, see SuiteScript Best Practices.
Best practices for coding promises:
-
Always use a promise rejection by including a promise.catch handler.
-
Do not nest promises. Chain your promises instead. Or use
async
/await
functionality. -
Keep promise chains short to avoid significant overuse of memory and CPU.
-
Use
promise.finally
if you have code that should run regardless of the outcome of the promise. -
Use
promise.all
for multiple unrelated asynchronous calls. -
Do not define rejection handlers as the second argument for
promise.then
calls. Instead, usepromise.catch
. -
If you need to access results of promises running in parallel, use
promise.spread
. -
To limit concurrency, use
promise.map
. -
Use
promise.then
to run code after the promise completes.
For additional best practice guidance when coding promises, see Best Practices for ES6 Promises, Best Practices for Using Promises in JS, JavaScript Promises Tips and Tricks, Promises (Mozilla), JavaScript Best Practices for Promises, and Promises.
Best practices when using async
and await
keywords:
-
Rewrite promise code to use
async
/await
. -
Schedule first, await later.
-
Avoid mixing callback-based APIs with promise-based APIs.
-
Refrain from using
return
await
. -
Remember that for SuiteScript 2.1 server-side scripts, only a subset of modules support the use of the
async
andawait
keywords: N/http, N/https, N/llm, N/query, N/search, and N/transaction.
For additional best practice guidance when using async
/await
, see Best Practices for ES2017 Asynchronous Functions, and Making asynchronous programming easier with async and await.
SuiteScript 2.x Promise APIs
The available promise APIs are named so that they correspond with their synchronous counterparts. Promise APIs have names that are suffixed with .promise
. For example, the search.create(options)
API has a promise version named search.create.promise(options)
. The following promise APIs are supported for 2.x client scripts and 2.1 server scripts:
Module |
Promise API |
Supported in SuiteScript 2.x Client Scripts |
Supported in SuiteScript 2.x Server Scripts |
---|---|---|---|
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
— |
|
||
— |
|
||
— |
|
||
|
|
||
|
|
||
|
|
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
— |
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
For supported modules members and additional API information, see SuiteScript 2.x Modules.
Examples
The following is a basic example of how to use the search.create.promise
in a client script for the pageInit
entry point.
/**
* @NApiVersion 2.x
*/
define(['N/search'], function(search)
{
function doSomething()
{
search.create.promise({
type: 'salesorder'
})
.then(function(result) {
log.debug("Completed: " + result);
//do something after completion
})
.catch(function(reason) {
log.debug("Failed: " + reason)
//do something on failure
});
}
return
{
pageInit: doSomething
}
});
This example demonstrates how to chain promises created with SuiteScript promise APIs.
/**
* @NApiVersion 2.x
*/
define(['N/search'], function(search)
{
function doSomething()
{
var filter = search.createFilter({
name: 'mainline',
operator: search.Operator.IS,
values:['T']
});
search.create.promise({
type: 'salesorder',
filters:[filter]
})
.then(function(searchObj) {
return searchObj.run().each.promise(
function(result, index){
//do something
})
})
.then(function(result) {
log.debug("Completed: " + result)
//do something after completion
})
.catch(function(reason) {
log.debug("Failed: " + reason)
//do something on failure
});
})
return
{
pageInit: doSomething
}
});
Custom Promises
The following example shows a custom promise. Note that custom promises do not use the SuiteScript 2.x Promise APIs.
/**
* @NApiVersion 2.x
*/
define(function(){
function doSomething(addresses){
var promise = new Promise(function(resolve, reject){
var url = 'https://your.favorite.maps/api/directions?start=' + addresses.start + '&end=' + addresses.end,
isAsync = true,
xhr = new XMLHttpRequest();
xhr.addEventListener('load', function (event) {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
resolve(xhr.responseText );
}
else {
reject( xhr.statusText );
}
}
});
xhr.addEventListener('error', function (event) {
reject( xhr.statusText );
});
xhr.open('GET', url, isAsync);
xhr.send();
});
return promise;
}
return {
lookupDirections: doSomething
};
});