【问题标题】:XMLHttpRequest to webservice not working in web worker对 Web 服务的 XMLHttpRequest 在 Web Worker 中不起作用
【发布时间】:2012-06-26 10:55:27
【问题描述】:

如果从主 javascript 调用下面的代码可以完美运行,但它不会在 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);
        }
    }


web worker 代码的唯一区别是它使用 postMessage 来返回结果:

<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>


启动worker的主要javascript:

  $(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);

    }



Web Worker 启动,参数正确,但 result.d 未定义。 catch 没有 statusText,只有 readyState=0status=0

这是什么魔法???



更新

xhr.responseText 如果从主 Javascript 调用是:

   {"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..............."}

【问题讨论】:

  • 如果将整个结果发送给父级会怎样?
  • @Jivings 结果也未定义
  • @Jivings 使用 FF13 和 Chrome 19。
  • 您确定您的网络服务正在返回数据吗?
  • @Jivings 我问题的第一部分显示了我在主 javascript 中测试的相同功能。它在那里完美运行并返回数据。

标签: html xmlhttprequest web-worker


【解决方案1】:

好吧,我在这里真的很愚蠢。我得到这个的原因

 DOMException: INVALID_STATE_ERR


是因为根据W3 documentation,如果 xhr.readyState 具有无效值,则 xhr.status 属性会引发异常:

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


我的 xhr.readyState 无效,因为我没有指定我正在调用的 Web 服务的完整路径。 需要网络服务的完整路径,因为网络工作者在“动态”创建的单独 Blob 文件中运行。

无论如何,下面是带有工作 web 服务调用脚本的 webwoker 代码:

<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>

【讨论】:

  • 嗨,我遇到了同样的错误。我正在尝试在网络工作者(~6MB)中上传大量图像。它适用于 1 或 2 个文件,但对于更多文件 ~6 个文件则失败。 Web Worker 是否存在一些内存限制?
  • 此修复还解决了我收到的 InvalidURL 消息。谢谢!
【解决方案2】:

对于 cmets,您的例外是:

DOMException: INVALID_STATE_ERR

这意味着您发送回父级的消息内容无法序列化。

根据我的经验,这通常是因为对象中存在循环引用或函数。在不知道服务器给出的响应的情况下,这是我可以帮助您的。

【讨论】:

  • AFAIK 当我使用 postMessage(result.d) 将数据传递给主 javascript 时,浏览器会将其解析为 JSON。 Web 服务将 HTML 表作为字符串返回。我将如何返回它以便它可以被序列化?
  • @EwaldStieger 您必须先发布网络服务响应。
  • 尝试在返回 {"d":"\"Hello World\""} 的 web worker 中调用一个简单的方法,但仍然得到相同的错误。会不会是权限问题,因为 web 服务是在 blob 中调用的?
  • @EwaldStieger:可能我并没有真正理解你的那部分代码。
猜你喜欢
  • 2015-02-21
  • 2017-03-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-13
相关资源
最近更新 更多