I rarely read the release notes because I’m in a hurry to get to the good stuff. APEX 5.0 has plenty of good stuff to get to but I want to call your attention to one release note in particular: “Deprecated Synchronous Ajax in Dynamic Actions”
Earlier this year there was an interesting thread on the APEX forums titled Synchronous requests deprecated. It points out that some browsers are now giving warnings (if you have the console open) when synchronous ajax requests are made and, more importantly, that APEX apps that use dynamic actions with Wait For Result set to
Yes will make a synchronous request.
This APEX 5.0 release note is letting you know that in the future APEX will be fixed so that dynamic actions will make asynchronous ajax requests. So check now to make sure your apps do not depend on the current synchronous behavior (and tell your friends). In the above thread I describe a couple of situations to avoid that depend on synchronous behavior.
The purpose of this post is to provide an example of what to do if you can’t wait for the future and need to make asynchronous requests today.
I created a demo app that shows the difference between synchronous and asynchronous ajax. To following along you will need to download the demo and import it into APEX 5.0. Note: the techniques provided here should also work with minor adjustments in APEX 4.2.
Next try the async version. Notice that the UI is not frozen and the progress spinner is visible and you can tell that the button is disabled during the request.
To turn the sync version into an equivalent async version do the following:
-- simulate checking for availability of a given quantity of tickets for a given event -- where it could take a while to get a result wwv_flow_utilities.pause(5); if :P3_EVENT = 'E2' then :P3_AVAIL := 'Sold Out'; elsif :P3_QUANTITY > 8 then :P3_AVAIL := 'Not enough seats available'; else :P3_AVAIL := 'OK'; end if;
- Add code to the Ajax Callback process to return any needed page items. One very nice thing that PL/SQL dynamic actions do is let you specify the page items to submit and page items to return. The current value of the page items to submit are read and put into the ajax request and are available as bind variables in the PL/SQL code block. The page items to return are bind variables that you assign to and then are returned in the ajax response and the page item current value is updated. Ajax Callback processes don’t let you declare page items to return. This is because these processes are general purpose and let you return anything you want. The demo returns a single page item value. Here is the added code:
-- use the new apex json api to return a list of page items to set -- this would need to be adjusted for APEX 4.2 apex_json.open_object; apex_json.open_array('item'); apex_json.open_object; apex_json.write('id', 'P3_AVAIL'); apex_json.write('value', :P3_AVAIL); apex_json.close_object; apex_json.close_array; apex_json.close_object;
This code can be broken down into 3 parts. Part 1 is a call to the
CHECK_AVAILprocess created in step 1 using the
apex.server.processAPI. This API makes it easy to submit page items just like the previous PL/SQL action did. The function
apex.server.processinitiates the ajax request to the server but doesn't wait for a response. Instead it returns a deferred object which is assigned to variable
jqxhr. At this point the dynamic action event handler is done. When the request is complete the function passed to the done method of the deferred object is called. The second and third parts happen inside this function once the request is complete.
Part 2 is processing the page items returned. The generic code used here will work for any page items if they are returned from the process in the same way. It sets the page item value to what the server returned.
That's all there is to it. Admittedly it is more complicated than the dynamic action only solution. If the synchronous ajax isn't currently bothering you then leave well enough alone and know that as long as you don't rely on the synchronous behavior your app should keep working without change when dynamic actions are changed to be asynchronous.
This technique uses documented APEX APIs so it will continue to work even after dynamic actions change. However you may want to switch back to the pure dynamic action method because it is simpler.
If nothing else this should give you a greater appreciation of all the work that APEX dynamic actions do for you. But knowing this technique opens up additional possibilities that can't be done with dynamic actions alone. For example what if you wanted to make 3 ajax requests in parallel and then after all 3 have finished do some client side processing. The
apex.server API along with jQuery deferreds will allow you to do that.