XMLHttpRequest在phantomjs中异步失败

XMLHttpRequest fails asynchronously within phantomjs

本文关键字:异步 失败 phantomjs XMLHttpRequest      更新时间:2023-09-26

我有一些相当简单的代码,可以使用XMLHttpRequest从url中获取一些数据。。。所有通常的东西,没有太不寻常的,例如:

var request = new XMLHttpRequest();
request.onload = function() { ... };
request.open("GET", url, true);
request.timeout = 5000;
request.send();

当这些代码在标准浏览器上下文中运行时,一切都很好。然而,当通过phantomjs调用(在运行node.js应用程序的服务器上调用(时,似乎只有当request.open()被指定为同步时(使用false作为最终参数(,相同的代码才能工作。因此,在phantomjs中,使用sync时可以很好地工作,但不使用async。当运行async时,请求永远不会成功完成。

在没有进一步的示例代码的情况下,为什么会出现这种情况,有明显的原因吗?也许我打破了phantomjs和/或XMLHttpRequest的一些规则。

到目前为止,我刚刚接受了它,并确保请求在phantomjs中是同步的,在浏览器中是异步的。但现在我正在尝试正确设置超时,因为我怀疑超时在同步模式下不能正常工作,但在异步模式下可能会正常工作,所以我试图使调用异步,即使在phantomjs中也是如此。即便如此,我还是担心超时不会像您在phantomjs中预期的那样工作。

任何专门针对sync/async问题的帮助都会很好,更好的是关于在phantomjs中超时工作的建议。

感谢Artjom B.的评论,我已经找到了问题所在。这可能是一个初学者的错误,因为我没有立即意识到,当事情在对象创建调用中异步发生时(var x = new MyThing(),其中MyThing的构造函数做了很多耗时的事情,包括XMLHttpRequest调用(,那么我需要在创建对象的代码中处理它。。。否则,我会试图在对象真正完成创建之前引用它。

因此,以下是我在创建对象(在其中进行XMLHttpRequest调用(时所做的操作:

var thing;
function myFunction() {
    // set up a flag and flag-setting callback function
    var fin = false;
    function setFlag () {
        fin = true;
    }
    // this is what takes time, and with async XMLHttpRequest calls
    // pass the callback function, which is run in the object constructor as the final step
    thing = new MyThing(setFlag); 
    // keep checking if the MyThing code has completed (based on 'fin' flag), then continue with doTheRest() when it has
    var interval = window.setInterval(function () {
        if (fin) {
            clearInterval(interval);
            doTheRest();
        }
    }, 50);
}

然后,一旦完成上述操作就开始执行函数doTheRest()。。。

function doTheRest() {
    // do some processing to generate some stuff required to be rendered on the page, using the 'thing' object created before...
    var stuff = doSomeProcessing(thing);
    if (typeof window.callPhantom === 'function') {
        window.callPhantom(stuff);
    }
}

window.callPhantom()调用是使代码异步工作所需的核心,这里对此进行了描述。它与page.onCallback回调函数配对,在运行page.evaluate()函数之前定义该函数,该函数实际上首先启动了主代码(如上(:

page.onCallback = function(svg) {
    // finally we've got the data we need, and can use it...
    // and only in the function below do we ever call phantom.exit(), so we have ensured that we don't exit phantomjs before we have got and used the data 
    renderSVG(svg);
};
page.open('about:blank', function (status) {
        page.evaluate(myFunction);
    }
});

有关该主题的更多信息,请参阅此处。

希望这有一天能帮助到其他人,甚至是否决我最初问题的人。