Promises
A promise is a placeholder for the return value of an operation that has been called asynchronously. It enables you to specify subsequent actions to be performed with that value when it is eventually received.
Promises enable you to easily and consistently handle asynchronous activation of server-side and client-side code. They make code more understandable because they do not required the server-side and client-side code to mutually call each other.
Promises are part of the next ECMAScript standard, and make it easier to chain actions and handle errors. Uniface promises are compliant with the Promises/A+ specification. For more information on Promises/A+ and the draft ECMAScript standard, see the following web sites: https://promisesaplus.com/ and ECMAScript® 2015 Language Specification: Promise Objects. There is, of course, much more information available on the web on how you can use promises.
The Uniface JavaScript API supports the use of promises for the createInstance(), activate(), and all the uniface.datastore functions. These functions return JavaScript promise objects.
To handle a promise, use the then method as part of the call to the function. For example:
ComponentInstance.activate(
{OperationName{,
Parameters}).
then(PromiseFullfilledAction,
PromiseRejectedAction);
Understanding Promises
To better understand how to use promises and the advantages promises have, assume you have a DSP in which we want to display the coordinates of an address on a map. To do this, the client-side JavaScript code calls a server-side operation that returns the address coordinates, which are then used to update a Google map.
To implement this functionality without promises, the following code is required:
; Detail trigger of a field webtrigger onClick javascript window.address = getAddress(); uniface.activate("lookupcoordinates", address) endjavascript end
; Operations container of the component operation lookupcoordinates public web params string address: in endparams call CalcCoordinates(LATITUDE.C.LOCATION, LONGITUDE.C.LOCATION) and webactivate $instancename.updatemap() end weboperation updatemap javascript var occ = uniface.getEntity("C.LOCATION").getOccurrence(0); google.maps.locate(occ.getField("LATITUDE").getValue(), occ.getField("LONGITUDE").getValue(), window.address); endjavascript end
- The onClick trigger
of a field calls a server-side operation called
lookupcoordinates
. - The operation
lookupcoordinates
calculates the coordinates of an address. - It then calls a web operation called
updatemap
. This is a callback to the client-side code, and therefore assumes that thelookupcoordinates
operation can only be called from browser and never by server-side code. - The
updatemap
web operation sets the address coordinates on a Google map.
There are several issues with this code:
- The server-side operation
lookupcoordinates
is closely intertwined with what the client wants to do with the result. It must call the appropriate operation on the browser. This is not information that should be handled at this level and means that the operation cannot be called by other operations or components. - If the
lookupcoordinates
operation call fails, there is no feedback to the user. - If the originating trigger needs to share state with the callback operation, it needs to go via a global variable.
- The code is convoluted and hard to follow.
The Uniface JavaScript API supports the use of promises for the createInstance() and activate() functions. These functions return JavaScript promise objects.
To handle the promise returned by the activate() function, you can use the following code:
; onClcick trigger of a field webtrigger onClick javascript var address = getAddress(); uniface.activate("lookupcoordinates", address).then( function() {var occ = uniface.getEntity("C.LOCATION").getOccurrence(0); google.maps.locate(occ.getField("LATITUDE").getValue(), occ.getField("LONGITUDE").getValue(), address); }, function(e){ alert("lookup failed"); }); endjavascript end
; Operations container of the component operation lookupcoordinates public web params string address: in endparams call CalcCoordinates(LATITUDE.C.LOCATION, LONGITUDE.C.LOCATION) end
- The onClick trigger
of a field calls a server-side operation called
lookupcoordinates
. - The then method handles the promise. It specifies what to do if the promise is fullfilled (the action succeeded) and what to do if it is rejected (the action relating to the promise failed).
- If the promise is fulfilled, it resolves to a value, which can be used in a subsequent action, in this case to update the Google map.
- If the promise is rejected, an error object is returned, and an error message is displayed.
- The operation
lookupcoordinates
calculates the coordinates of an address. It does not need to know anything about how it was called.