XMLHttpRequest to webservice not working in web wo

2020-06-27 09:03发布

问题:

The code below runs perfectly if called from main javascript, but it does not run in the web worker.

  function getSpecData(detailLvl, startWeek, endWeek, mkt) {
        var params = { "detailLvl": detailLvl, "startWeek": startWeek, "endWeek": endWeek, "mkt": mkt };
        var xhr;
        var url = "WebServices/wsSProgress.asmx/GetSpecProgressTable";
        try {
            xhr = new XMLHttpRequest();
            xhr.open('POST', url, false);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = JSON.parse(xhr.responseText);
                    $('#specProgTbl').html(result.d);
                }
            };
            xhr.send(JSON.stringify(params));
        } catch (e) {
            alert('Error occured in XMLHttpRequest: ' + xhr.statusText + '  ReadyState: ' + xhr.readyState + ' Status:' + xhr.status);
        }
    }


The only difference in the web worker code is that it uses postMessage to return the result:

<script id="worker" type="javascript/worker">

    self.onmessage = function (e) {
        var data = e.data;
        //self.postMessage(data.mkt + " " + data.detailLvl + " " + data.refreshMin + " " + data.isRotate +" "+data.weekNum);

        var startWeek=data.weekNum-3;
        var endWeek=data.weekNum;
        self.postMessage(getSpecData(1,startWeek,endWeek,data.mkt));

    }; 
    function getSpecData(detailLvl, startWeek, endWeek, mkt) {
        self.postMessage('DetailLvl '+detailLvl+' Start '+startWeek+' End '+endWeek+' Mkt '+mkt); 
        var params = { "detailLvl": detailLvl, "startWeek": startWeek, "endWeek": endWeek, "mkt": mkt };
        var xhr;
        var url = "WebServices/wsSpecProgress.asmx/GetSpecProgressTable";
        try {
            xhr = new XMLHttpRequest();
            xhr.open('POST', url, false);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = JSON.parse(xhr.responseText);
                    self.postMessage(result.d);
                }
            }; 
            xhr.send(JSON.stringify(params));
        } catch (e) {
            self.postMessage('Error occured in XMLHttpRequest: ' + xhr.statusText + '  ReadyState: ' + xhr.readyState + ' Status:' + xhr.status);
        }
    }

</script>


The main javascript starting the worker:

  $(function initialize() {
        $('#options').hide();
        $("[id$='btnViewOpt']").val("View Options");
        var mkt = $("[id$='lstMkt'] :selected").text();
        var detailLvl = $("[id$='lstDetailLvl'] :selected").val();
        var refreshMin = $("[id$='lstRefresh'] :selected").val();
        var isRotate = $("[id$='chkRotate']").is(":checked");

        var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder;
        window.URL = window.URL || window.webkitURL;
        if (BlobBuilder) {
            var bb = new BlobBuilder();
            bb.append(document.querySelector('#worker').textContent);
            wUrl = window.URL.createObjectURL(bb.getBlob());
            worker = new Worker(wUrl);
            alert("Web worker started");
            worker.addEventListener('message', dispMsg, false);
            worker.addEventListener('error', onError, false);
            worker.postMessage({ 'mkt': mkt, 'detailLvl': detailLvl, 'refreshMin': refreshMin, 'isRotate': isRotate, 'weekNum': getCurrentWeekNumber() }); // Start the worker.
        }
        else
            alert("Your browser does not support web workers");
 });

  function onError(e) {
        alert('ERROR in WebWorker: Line ' + e.lineno + ' in ' + e.filename + ': ' + e.message);
    }
    function dispMsg(e) {
        alert("Message from worker: " + e.data);
        $('#specProgTbl').html(e.data);

    }



The web worker starts and the params are correct but result.d is undefined. The catch has no statusText and just readyState=0 and status=0.

What sorcery is this???



UPDATE

xhr.responseText if called from main Javascript is:

   {"d":"\u003ctable border=\u00271px\u0027 cellpadding=\u00275\u0027 cellspacing=\u00270\u0027\u003e\u003ctr height=\u002710\u0027 \u003e\u003cth height=\u002710\u0027 colspan=\u002712\u0027\u003ePAS\u003c/th\u003e\u003c/tr\u003e\u003ctr height=\u002710\u0027 \u003e\u003ctd align=\u0027center\u0027 width=\u0027200\u0027\u003eManufacturer\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027150\u0027\u003eMake\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eNoSpec W22\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eComplete% W22\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eNoSpec W23\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eComplete% W23\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eNoSpec W24\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eComplete% W24\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eNoSpec W25\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eComplete% W25\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eNoSpec W26\u003c/td\u003e\u003ctd align=\u0027center\u0027 width=\u0027100\u0027\u003eComplete% W26\u003c/td\u003e\u003c/tr\u003e\u003ctr height=\u002710\u0027 \u003e\u003ctd align=\u0027left\u0027  class=\u0027default\u0027  height=\u002710\u0027 \u003eAAD\u003c/td\u003e\u003ctd align=\u0027left\u0027  class=\u0027default\u0027  height=\u002710\u0027 \u003eCHERY\u003c/td\u003e\u003ctd align=\u0027left\u0027 class=\u0027noSpecSame\u0027  height=\u002710px\u0027 \u003e0\u003c/td\u003e\u003ctd align=\u0027center\u0027  class=\u0027percSame\u0027  height=\u002710\u0027 \u003e\u003cdiv style=\u0027background-image: linear-gradient(left , rgba(8,68,250,1) 18%, rgba(240,241,250,1) 92%, rgba(240,241,250,0) 8%);background-image: -o-linear-gradient(left , rgba(8,68,250,1) 18%, rgba(240,241,250,1) 92%, rgba(240,241,250,0) 8%);background-image: -moz-linear-gradient(left , rgba(8,68,250,1) 18%, rgba(240,241,250,1) 92%, rgba(240,241,250,0) 8%);background-image: -webkit-linear-gradient(left , rgba(8,68,250,1) 18%, rgba(240,241,250,1) 92%, rgba(240,241,250,0) 8%);background-image: -ms-linear-gradient(left , rgba(8,68,250,1) 18%, rgba(169,199,245,1) 92%, rgba(240,241,250,0) 8%);background-image: -webkit-gradient(linear,left bottom,right bottom,color-stop(0.18, rgba(8,68,250,1)),color-stop(0.92, rgba(240,241,250,1)),color-stop(1, rgba(240,241,250,0)));\u0027\u003e92\u003c/div\u003e\u003c/td\u003e\u003ctd align=\u0027left\u0027 class=\u0027noSpecSame\u0027  height=\u002710\u0027 \u003e0\u003c/td\u003e\u003ctd align=\u0027center\u0027  class=\u0027percSame\u0027 height=\u002710\u0027 \u003e\u003cdiv style=\u0027background-image: linear-gradient(left , rgba(8,68,250,1) 18%, rgba(240,241,250,1..............."}

回答1:

Ok I was really stupid here. The reason why I was getting the

 DOMException: INVALID_STATE_ERR


was because according to W3 documentation the xhr.status attribute throws an exception if xhr.readyState has an invalid value:

    Exceptions on retrieval
    DOMException  INVALID_STATE_ERR exception SHOULD be raised if this attribute is accessed when readyState has an inappropriate value. 


I had an invalid xhr.readyState since I did not specify a full path to the webservice I am calling. The full path to the webservice is needed because the webworker runs in the separate Blob file created "on the fly".

Anyway, below is the webwoker code with working webservice call script:

<script id="worker" type="javascript/worker">

    self.onmessage = function (e) {
        var param = e.data;
        var url="http://localhost:54071/WebServices/wsSProgress.asmx/GetSpecProgressTable";
        var data=getSpecData(param.detailLvl,param.startWeek,param.endWeek,param.mkt,url)
        self.postMessage(data);
    }; 
    function getSpecData(detailLvl, startWeek, endWeek, mkt, url) {
        var params = { "detailLvl": detailLvl, "startWeek": startWeek, "endWeek": endWeek, "mkt": mkt };
        var xhr;
        try {
            xhr = new XMLHttpRequest();
            xhr.open('POST', url, false);
            xhr.setRequestHeader('Content-Type', 'application/json');
            xhr.onreadystatechange = function () {
                if (xhr.readyState == 4 && xhr.status == 200) {
                    var result = JSON.parse(xhr.responseText);
                    self.postMessage(result.d);
                }
            }; 
            xhr.send(JSON.stringify(params));
        } catch (e) {
            self.postMessage('Error occured in XMLHttpRequest: ' + xhr.statusText + '  ReadyState: ' + xhr.readyState + ' Status:' + xhr.status + ' E: ' +e+' Msg:'+e.message);
        }
    }
    </script>


回答2:

From comments, your exception is:

DOMException: INVALID_STATE_ERR

This means that the contents of your message being posted back to the parent cannot be serialized.

In my experience, this is usually because of circular references or functions present in the object. Without knowing the response that the server is giving, this is as much as I can help you.