Synchronous requests deprecatedSaraB Feb 18, 2015 12:48 PM
Hi
I apologise if this has been raised elsewhere. I've searched the forum, the requested features and the release notes for APEX 5.0 and can see no mention of this. I've also tested in APEX 5.0.
Dynamic actions using the Wait For Result option to guarantee execution order use synchronous XMLHttpRequest. Synchronous XMLHttpRequest on the main thread is now deprecated and support will be removed from browsers at some point in the future:
Browsers are already issuing warnings about this: [Chrome] Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.
If browsers drop support for synchronous XMLHttpRequest before APEX stops using it APEX developers will face big problems.
How does the APEX team intend to handle this? Is this something that is being considered for APEX 5.0 or even an update to 4.x?
Many thanks
Sara
1. Re: Synchronous requests deprecatedDenes Kubicek Feb 19, 2015 8:06 AM (in response to SaraB)
This is indeed a good question. Hopefully someone from the team will have a look at it and answer.
Denes Kubicek
2. Re: Synchronous requests deprecatedScott Wesley Mar 6, 2015 2:01 AM (in response to Denes Kubicek)
Can anyone from the APEX team shed light on how apex.server.process is managing this behind the scenes?
Here is a brilliant stackoverflow post describing the issue and methods to restructure code if necessary
javascript - How to return the response from an asynchronous call? - Stack Overflow
It will also be handy to know if the success error keywords will be replaced with done failure.
I've referenced this post within the APEX EA feedback.
3. Re: Synchronous requests deprecatedJohn Snyders-Oracle Mar 11, 2015 2:51 PM (in response to SaraB)1 person found this helpful
The APEX development team is aware of the negative impact of using synchronous ajax requests and that browsers are now issuing warnings. We have been working over the past few release to remove synchronous ajax but the work will not be completed in 5.0. Going forward we intend to replace all synchronous ajax requests with asynchronous ones.
APIs in the apex.server namespace such as apex.server.process and apex.server.plugin use jQuery to make ajax requests. They default to doing async requests (because async=true by default). Because you can pass in options for jQuery.ajax it will be possible to set async: false for as long as jQuery and browsers still support that. But hopefully we all know by now that setting async: false is never a good idea. So if you use the APEX server APIs and don't override the default you will be doing async ajax.
The return value of apex.server.process and apex.server.plugin is the jQuery.ajax jqXHR value. I don't think there are any places in APEX outside the server module where we use the jqXHR return value. We do not use the deprecated jqXHR success, error or complete methods. I doubt many APEX developers use jqXHR as deferreds/promises are likely unfamiliar concepts. But if you do have code that uses jqXHR success, error or complete methods then you should switch to using done, fail, or always. The deprecation notice does not apply to the jQuery.ajax success, error, and complete settings (APEX server APIs document these settings as pOptions). These call back functions are probably what most people are using and will continue to work.
For Dynamic Actions that use Wait For Result equal to yes it is unfortunate that APEX will issue a synchronous ajax request (even in 5.0). We almost switched to using async ajax in 4.2 but we did not because during upgrade testing we found that it adversely affected some applications. This shows how important backward compatibility is for APEX. We found that some applications relied on the synchronous behavior of dynamic actions. The release notes for 5.0 will be updated to include a statement that applications must not depend on the currently synchronous behavior of dynamic actions with wait for result equal yes. In the future, when APEX does switch to using async ajax for dynamic actions with wait for result equal to yes the change should be transparent, there is nothing you will need to do providing that you are not relying on the synchronous behavior.
This raises 3 questions
1) when will APEX switch to async for dynamic actions?
2) how do I know if I'm relying on synchronous behavior?
3) what if I can't wait and I need to do async requests with dynamic actions now?
It should be no surprise I can't answer the first question.
It should be rare that you depend on ajax requests being synchronous. The case that we found people using (more accurately abusing) was sending an ajax request in response to the Page Unload (unload) or Before Page Submit (apexbeforepagesubmit) events. These events cannot be stopped and are not intended to have lengthy processes performed. When the user submits or navigates away from a page they do not want to be delayed. When the page unloads any outstanding ajax requests are aborted. So if you do an async ajax request from the page unload event, for example, it will be aborted before it is even sent.
Another, probably even more rare case of depending on synchronous behavior is if you started two Execute PL/SQL Code dynamic actions, for example, in response to the same event with with for result equal yes on both of them and in the following actions assumed that one of the events would finish before the other.
To answer the 3rd question I should work up an example so that will have to wait.
4. Re: Synchronous requests deprecatedScott Wesley Mar 11, 2015 4:10 PM (in response to John Snyders-Oracle)
Thank you for such a comprehensive response.
Point 3 - can't you just untick the 'wait for result' box?
If you meant 'sync', could the synchronous behaviour associated with 'wait for result' be replicated with $,deferred functionality?
Regarding jqXHR, I found using the APEX api it didn't recognise done/fail, only success/error (in 4.2.0)
apex.server.process("MY_PROC",{ },{ error: function(pjqXHR, pTextStatus, pErrorThrown) {}, success:function(pData){} });
Apologies to Sara for hijacking the post a little here, but I think it's a worthy discussion for all
5. Re: Synchronous requests deprecatedSaraB Mar 11, 2015 5:00 PM (in response to John Snyders-Oracle)
Hi John
Thank you for your answer.
I'm a little confused by the response though, especially the line "release notes for 5.0 will be updated to include a statement that applications must not depend on the currently synchronous behavior of dynamic actions with wait for result equal yes". It seems that you are saying that applications shouldn't use the wait for result option, is my understanding correct?
Scott has suggested that you simply untick the wait for result option, but this isn't possible. Wait for result is important in dynamic actions and we use it a lot. I have set up the simplest example I could think of in the EA3 environment to try to illustrate my problem, it's accessible here::::: (there's no authentication on the application). I have a report region that is based on the value of an item on the page. The dynamic action has two actions:
1 - PL/SQL code that sets the item value in APEX - This has wait for result ticked
2 - Refresh the report region
So whenever the level item is changed the report region automatically refreshes. If wait for result wasn't ticked then the second action would fire at the same time and have no effect, until the level was changed again and then it would be refreshed based on the old value.
There is no other way I can see of this type of dynamic action working. It is a simple dynamic action, not doing anything particularly special, but all specific to APEX and extremely useful.
I don't fully understand the technical issues here, but I know that removing wait for result isn't a viable option unless I'm missing something obvious.
Many thanks for your help.
Sara
6. Re: Synchronous requests deprecatedStephen Blair Mar 11, 2015 5:29 PM (in response to Scott Wesley)1 person found this helpful
Scott, as you say synchronous behaviour can be achieved when using async requests by utilising the appropriate callbacks of the deferred objects returned by jQuery ajax.
I don't think "Wait for Result" needs to be deprecated, removed or advised against, if the output generated by APEX dynamic actions is updated to use callbacks of deferred objects instead of relying on the deprecated async=false option.
"Wait for Result" is a perfectly useful, declarative attribute as Sara's example illustrates. It's just the implementation that needs updating in APEX.
Regarding jqXHR, I found using the APEX api it didn't recognise done/fail, only success/error (in 4.2.0)
- apex.server.process("MY_PROC",{
- },{
- error: function(pjqXHR, pTextStatus, pErrorThrown) {},
- success:function(pData){}
- });
done/fail are methods of the Deferred object. error/success are callback options of $.ajax(). It is the error/success methods of the old (pre jQuery 1.5) jqHXR object that are deprecated, but the error/success callbacks are still valid. As John mentioned, apex.server.process won't be affected by the deprecation of these methods, only third party code that uses the Deferred object returned by apex.server.process
7. Re: Synchronous requests deprecatedJohn Snyders-Oracle Mar 12, 2015 1:17 AM (in response to SaraB)1 person found this helpful
I think Stephen covers most of the issues well but I'll add some details in the hopes of making things even more clear.
@Scot,
Yes you can uncheck (set to No) the Wait For Result attribute as long as you don't have subsequent actions that must run after that one completes. As Sara points out it is frequently the case that you need to wait.
In the future Dynamic Actions will never be synchronous regardless of if you set Wait For Result to Yes or No.
The APEX code is basically ready to go we just needed to give people fair warning before we get rid of the synchronous behavior.
As for the done/fail methods not being recognized, your example shows you using call back functions in the options argument. As Stephen points out done and fail are methods of the returned Deferred object known as jqXHR. Here is an example of how it is used
var jqXHR = apex.server.process("MY_PROC",{...}, {...});
jqXHR.done(function(...) {...});
Check out the jQuery documentation for all the cool things you can do with a deferred.
@Sara
Sorry my original response was confusing. APEX applications should continue to set Wait For Result to Yes if that is what they need to do. You give a good example of why it is needed. The Wait For Result option is not going away. Keep using it. Just don't rely on the request being synchronous (I gave some examples to avoid that do rely on synchronous behavior). In the future the ajax request will be async and your dynamic actions that uses wait for result will keep on working.
The tricky bit, which is where I think Scott is trying to go, is what if my app needs to be async now, today. What do I do given that checking wait for result will be synchronous?
This is where I still owe an example. It involves unchecking wait for result and extra JavaScript code using the apex.server APIs.
Why would you need to be async? One example is that your users complain that the UI freezes. This can happen if the PL/SQL processing takes too long or over a slow network. Another example is if the UI needs to do some processing while the ajax request is in flight.
-John
8. Re: Synchronous requests deprecatedJohn Snyders-Oracle Apr 16, 2015 1:34 AM (in response to SaraB)