locked
WebView ALWAYS fires onError for img element when loading a resource

    Question

  • Hello. 

    I'm using WebView to load Html page from the server with empty <img> elements and later assign "src" attribute when needed.

    HTML

        <div class="Content" data-p="main">
            <img id="latestMainImg" />
        </div>

    I use a Promise- to chain subsequent tasks-, and  $().on("event",function()}) to add "error" and "load" event handlers for the <img> element.

    // Uses jquery 1.11.1.min.js and ES6 Promise (https://github.om/jakearchibald/es6-promise)

    // prepare callbacks    var onL = function (resolve, reject) {     console.log("Loading MainImage * SUCCESS!");     resolve(true);    };    var onErr = function (resolve, reject) {      console.log("Loading MainImage * FAILED!");      $("#latestMainImg").attr("src", str_urlForBackupImage);      resolve(true);     }; // load main image    return loadImagePromise( "#latestMainImg", str_ImageUrl, onL, onErr, onErr); 

    loadImagePromise: function(str_selector, str_url, fn_onLoad, fn_onErr, fn_onTOut){ "use strict"; console.log("START loadImagePromise() for " + str_selector + " @ " + str_url); var t = $(str_selector); // Clear existing event listeners and "src" attribute t.off("load").off("error");       t.attr("src", "");

    return new Promise(function(resolve, reject){     "use strict";      var target = $(str_selector);      // set timeout      var tOutK = setTimeout(function(){          fn_onTOut(resolve, reject);      }, S.PM.imageLoadTOut);      console.log("SET TimeOutKEY : ", tOutK);      // set onLoad event handler      target.on("load", function(e){          //clear timeout          clearTimeout(tOutK);          console.log("CLEARED TimeOutKEY : ", tOutK);          fn_onLoad(resolve, reject);       });      // set onError event handler      target.on("error", function () {               //ignore onError in Windows' WebView          if (isWinWebView)         {            console.log("onERROR for loadImagePromise() ** ExMode : IGNORE");            console.log("for " + str_selector + " @ " + str_url);                    // Do nothing. The fn_onTimeOut will reject or the fn_onLoad will resolve.         }         else         {            //clear timeout            clearTimeout(tOutK);            fn_onErr(resolve, reject);         }    }); // set src attribute target.attr('src', str_url); }); // END of return new Promise() }// END of loadImagePromise

    I tested the JScript on Android WebView and Desktop Browsers(Chrome, IE, Opera, FireFox) and all of them fire the "Error" and "Load" events well as expected. But in my developing Windows Store App(targeting ver.8.1) using WebView, the WebView ALWAYS fires "Error" event as soon as I assign the "src" attribute to the img element. Then the "Load" event fires as soon as the resource is loaded. The WebView renders the loaded image successfully.

    -------------------- JS console log --------------------------------------------------------------------------------------------

    ...

    START loadImagePromise() for #latestMainImg @ https://{myDomain}/latestMain_12

    SET TimeOutKEY :  15

    onERROR for loadImagePromise() ** ExMode : IGNORE

    for #latestMainImg @ https://{myDomain}/latestMain_12

    CLEARED TimeOutKEY :  15

    Loading MainImage * SUCCESS!

    ...

    ----------------------------------------------------------------------------------------------------------------------------------

    The below is the request's info from Fiddler. It seems the http request itself doesn't have a problem, as far as I can deduce. (If there's a problem I can't get, please let me know.)

    ---------------------------------------------------------------------------------------------------------------------------------

    HTTP/1.1 200 OK
    Cache-Control: must-revalidate, max-age=1209600, private
    Content-Length: 369316
    Content-Type: image/png
    ETag: "0x8D15B5C4A175165"
    Date: Sun, 06 Jul 2014 07:37:32 GMT

    ------------------------------------------------------------------------------------------------------------------------

    SESSION STATE: Done.
    Response Entity Size: 369316 bytes.

    == FLAGS ==================
    BitFlags: [IsHTTPS, ClientPipeReused, ServerPipeReused] 0x19
    X-EGRESSPORT: 6797
    X-RESPONSEBODYTRANSFERLENGTH: 369316
    X-CLIENTPORT: 6796
    X-CLIENTIP: 127.0.0.1
    X-SERVERSOCKET: REUSE ServerPipe#1050
    X-HOSTIP: {myDomain's IP}
    X-PROCESSINFO: avp:7392

    == TIMING INFO ============
    ClientConnected: 16:37:26.250
    ClientBeginRequest: 16:37:34.113
    GotRequestHeaders: 16:37:34.113
    ClientDoneRequest: 16:37:34.113
    Determine Gateway: 0ms
    DNS Lookup: 0ms
    TCP/IP Connect: 0ms
    HTTPS Handshake: 0ms
    ServerConnected: 16:37:26.526
    FiddlerBeginRequest: 16:37:34.113
    ServerGotRequest: 16:37:34.113
    ServerBeginResponse: 16:37:34.417
    GotResponseHeaders: 16:37:34.418
    ServerDoneResponse: 16:37:35.356
    ClientBeginResponse: 16:37:35.356
    ClientDoneResponse: 16:37:35.364

    Overall Elapsed: 0:00:01.250

    The response was buffered before delivery to the client.

    == WININET CACHE INFO ============
    This URL is not present in the WinINET cache. [Code: 2]
    * Note: Data above shows WinINET's current cache state, not the state at the time of the request.
    * Note: Data above shows WinINET's Medium Integrity (non-Protected Mode) cache only.

    -----------------------------------------------------------------------------------------------------------------------------

    With that, I can't find why the WebView calls "Error" event. As in the function loadImagePromise(), I remove all listeners before I assign a new "src" to prevent "Error" called by any possible "abortion" and accumulation of handlers.  The code works well in the browsers I tested except  this Windows'  WebView.

    The unconditional "Error" event always occurs for every <img> elements, not only for that one specific image resource in the previous code. 

    I suspected that the WebView thinks the URLs which ends without extension as a bad resource(though the response's content type is "image/*") and tried a URL with ending extension like .jpg or .png . However the WebView called "Error" handler as well.

    I also suspected that JQuery's $(selector).on("error",function(){}) does not handle the <img>'s events well. So tried attach "onerror" handler with plain document.querySelector().onerror = function(){}.

    document.querySelector(str_selector).onerror = function () {
        //ignore onError in exMode 
     if (inWinWebView)
     {
    	 console.log("onERROR for loadImagePromise() ** ExMode : IGNORE");
    	 console.log("for " + str_selector + " @ " + str_url);
             // Do nothing. Timer will reject or OnLoad will resolve.
         }
     else
     {
    	//clear timeout
    	clearTimeout(tOutK);
    	 fn_onErr(resolve, reject);
     }
    };

    But the WebView had called the "onerror" handler before it has successfully loaded the image, reproducing the same  console log output as the previous log up there.

    After spending several days, I just decided to IGNORE the "Error" event - as the current version of the code above- when it's being executed in the Windows' WebView. But I want to know why and how to resolve the problem if I missed something deadly simple but important.

    It would be great if somebody tells me why or clarifies that it's the WebView's bug, which would help me to simply forget about this issue.

    Thank you in advance.





    • Edited by iyij Wednesday, July 09, 2014 8:51 AM
    Sunday, July 06, 2014 9:01 AM

Answers

  • Hi llyhx,

    Looks like the issue is related to a Jquery conflict since you mentioned ‘the WebView ALWAYS fires "Error" event as soon as I assign the "src" attribute to the img element'.

    As I can see you are using JQuery 1.1, not sure if this is the cause, but I would like ask you to try original Javascript like below:

    // Clear existing event listeners and "src" attribute
    
                    t.off("load").off("error");      
                    t.attr("src", "");
    
    To:
    
    // Clear existing event listeners and "src" attribute
    
        t.off("load").off("error");
    
        if (t.is('[src]')) {
            var objectdom = t[0];
            objectdom.removeAttribute("src");
        }
    

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by iyij Wednesday, July 16, 2014 9:42 AM
    Friday, July 11, 2014 1:58 AM
    Moderator

All replies

  • Hi llyhx,

    Looks like the issue is related to a Jquery conflict since you mentioned ‘the WebView ALWAYS fires "Error" event as soon as I assign the "src" attribute to the img element'.

    As I can see you are using JQuery 1.1, not sure if this is the cause, but I would like ask you to try original Javascript like below:

    // Clear existing event listeners and "src" attribute
    
                    t.off("load").off("error");      
                    t.attr("src", "");
    
    To:
    
    // Clear existing event listeners and "src" attribute
    
        t.off("load").off("error");
    
        if (t.is('[src]')) {
            var objectdom = t[0];
            objectdom.removeAttribute("src");
        }
    

    --James


    <THE CONTENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED>
    Thanks
    MSDN Community Support

    Please remember to "Mark as Answer" the responses that resolved your issue. It is a common way to recognize those who have helped you, and makes it easier for other visitors to find the resolution later.

    • Marked as answer by iyij Wednesday, July 16, 2014 9:42 AM
    Friday, July 11, 2014 1:58 AM
    Moderator
  • Hi James,

    Sorry for being late to reply to your help. I've just noticed today that you had given the answer 5 days ago. And soon I tried your code.

    Above all, I was surprised that the three lines of code totally have wiped out those annoying ERROR messages.

    How could you find the right point to fix? 

    As I posted, I tried to change the part of code at which assigning event handlers, but as your code has demonstrated, the problem seems to have been at the code removing the 'src' attribute using JQuery.

    Thank you for your great help!

    Wednesday, July 16, 2014 9:42 AM