[
https://issues.apache.org/jira/browse/CB-4873?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14079655#comment-14079655
]
Maris Seimanovs commented on CB-4873:
-------------------------------------
'System.SystemException' in InvokeScript is a different issue, not related to
messing up async requests.
But as I have experienced this SystemException myself, I can comment on it.
This exception happens if Javascript throws some error in your custom
Javascript callback function. Even if you add window.onerror handler to your
application, still your application will crash and exit because InvokeScript is
sensitive to all Javascript errors.
As a last resort workaround you can wrap the InvokeScript call with {code}try
{ InvokeScript ... } catch(SystemException){ } {code}. Maybe there is some
better solution to tell InvokeScript to ignore Javascript errors but I was lazy
and I just went with this workaround. Now I can catch and process all
Javascript errors and exceptions from window.onerror handler and show some
user-friendly error message instead of just quitting my Cordova application.
> XHRHelper is failing with simultaneous asynchronous requests
> ------------------------------------------------------------
>
> Key: CB-4873
> URL: https://issues.apache.org/jira/browse/CB-4873
> Project: Apache Cordova
> Issue Type: Bug
> Components: WP8
> Affects Versions: 3.0.0
> Environment: Any
> Reporter: Jonathan Naguin
> Assignee: Jesse MacFadyen
> Priority: Critical
> Labels: WP8, WP8.1, ajax, asynchronous, multiple, xhrhelper
> Attachments: CordovaWP8_3.6.0-dev1.zip, CordovaWP8_WP8.1_3.4.1.zip
>
>
> XHRHelper is failing in processing mutiple simultaneous asynchronous AJAX
> requests. I am using the latest code from
> https://github.com/apache/cordova-wp8/blob/master/wp8/template/cordovalib/XHRHelper.cs
> The problem is related with {{_onXHRLocalCallback}} which is save into the
> {{window}} object as a unique function. When, for example, two Ajax requests
> are evaluated at same time, the last {{funk}} function overrides the first
> {{_onXHRLocalCallback}} without receive the data from the C# code to that
> particular request.
> To demostrate this I put {{console.log("XHR: " + resolvedUrl);}} inside
> {{__onXHRLocalCallback}} and
> {{System.Diagnostics.Debug.WriteLine("HandleCommand: " + url);}} in
> {{HandleCommand}} method (my code uses *Require JS* to load this resources).
> The output is this:
> {code}
> HandleCommand: x-wmapp0:www/src/modules/home/HomeView.html
> HandleCommand: x-wmapp0:www/src/modules/orders/OrdersView.html
> XHR: x-wmapp0:www/src/modules/orders/OrdersView.html
> XHR: x-wmapp0:www/src/modules/orders/OrdersView.html
> XHR: HandleCommand: x-wmapp0:www/src/modules/order/OrderDetailView.html
> XHR: x-wmapp0:www/src/modules/order/OrderDetailView.html
> {code}
> As you can see, one request is missing: "HomeView.html".
> h6. NOTES
> - If I set {{false}} the {{this.isAsync}} variable it works (this way it is
> executed without using setTimeout).
> - If I put a console.log before launch {{funk}} it works.
> - It works on the simulator, but it fails on a real device.
> h6. Possible solution
> In conclusion, I assumed that it's a timing problem. To resolve it I decided
> to save a onXHRLocalCallback function per each request:
> {code}
> var funk = function () {
> if (! window.__onXHRLocalCallback){
> window.__onXHRLocalCallback = {}; //Object to store the functions
> }
>
> window.__onXHRLocalCallback[resolvedUrl] = function (responseCode,
> responseText) {
> alias.status = responseCode;
> if (responseCode == '200') {
> alias.responseText = responseText;
> }
> else {
> alias.onerror && alias.onerror(responseCode);
> }
> alias.changeReadyState(XHRShim.DONE);
> delete window.__onXHRLocalCallback[resolvedUrl]; //Delete the function
> }
> alias.changeReadyState(XHRShim.LOADING);
> window.external.Notify('XHRLOCAL/' + resolvedUrl);
> }
> {code}
> So I had to change in {{HandleCommand}} method the way of invoking this
> callback. I decided to create a helper function to be called in each case:
> {code}
> /// <summary>
> /// Invoke a XHR callback
> /// </summary>
> /// <param name="url">The URL of the request</param>
> /// <param name="code">The response code</param>
> /// <param name="text">The response text</param>
> private void InvokeCallback(string url, int code, string text)
> {
> string args = string.Format("('{0}', {1}, {2});", code,
> WPCordovaClassLib.Cordova.JSON.JsonHelper.Serialize(text),
> WPCordovaClassLib.Cordova.JSON.JsonHelper.Serialize(url));
> string callback = @"(function(code, text, url){
> try {
> window.__onXHRLocalCallback[ url ].call(null, code, text);
> }
> catch(e) {
> console.log('Error calling method from XHRHelper :: ' + e);
> }
> })" + args;
> Browser.InvokeScript("eval", new string[] { callback });
> }
> {code}
> To be called as {{InvokeCallback(url, 200, text);}} or {{InvokeCallback(url,
> 404, null);}}
> Thanks.
--
This message was sent by Atlassian JIRA
(v6.2#6252)