当请求DOM对象时,XMLHttpRequest.send()抛出异常

XMLHttpRequest.send() throws exception when asked for a DOM object

本文关键字:send 抛出异常 XMLHttpRequest 请求 DOM 对象      更新时间:2023-11-14

我想在Firefox/Greasemonkey用户脚本中检索一个HTML页面作为document

编辑:这不是跨域请求。

这是我的示例代码:

var r = new XMLHttpRequest();
r.open("GET", document.location.href, true);
r.responseType = "document";
r.send(null);

这看起来就像中的示例https://developer.mozilla.org/en/HTML_in_XMLHttpRequest,但是CCD_ 2引起CCD_。原因,而不是投掷!在try...catch中换行不会改变任何内容,它看起来像是回调或事件处理程序引发了异常:

TypeError: document.location is null

回溯引用的是Firefox内部的event.js文件,但不是我的脚本。

删除设置responseType的行可以消除异常,添加回调则不能。但是,响应是有效的,并且responseXML提供了DOM树。我使用的是FF 13.0.1。

我是错过了什么,还是这是个bug?

解决方案:这与Mozilla的Addon Builder创建的扩展有关,而不是Firefox。

脚本正在google.com上运行,您正在尝试获取google.de,对吗?这是一个跨域请求(此外,问题代码不是XMLHttpRequest的有效同步或异步使用。)

要在Greasemonkey脚本(或Chrome)中执行跨域(或不执行)AJAX,请使用GM_xmlhttpRequest()
请注意,GM_xmlhttpRequest()当前不允许您指定responseType,但在这种情况下您不需要这样做。如果您想要一个好的解析文档,请使用DOMParser

综合起来:

GM_xmlhttpRequest ( {
    method:     'GET',
    //url:        'https://www.google.de/',
    url:        location.href,  // self get, checking for updates
    onload:     function (respDetails) {
                    processResponse (respDetails);
                }
} );
function processResponse (respDetails) {
    // DO ALL RESPONSE PROCESSING HERE...
    var parser  = new DOMParser ();
    var doc     = parser.parseFromString (respDetails.responseText, "text/html");
    //--- Example showing that the doc is fully parsed/functional...
    console.log (doc.querySelectorAll ("p") );
}




PS:由于这毕竟不是跨域的,更正的原始代码将是:

var r           = new XMLHttpRequest();
r.onload        = function () {
    // DO ALL RESPONSE PROCESSING HERE...
    console.log (this.response.querySelectorAll ("div") );
}
r.open ("GET", location.href, true);
r.responseType  = "document";
r.send (null);

用于异步请求。

不幸的是,您无法从一个域到另一个域执行Ajax:

http://en.wikipedia.org/wiki/Same_origin_policy

你可以阅读CORS:

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing

或JSONP作为可能的解决方案:

http://en.wikipedia.org/wiki/JSONP

然而,浏览器的设计方式使得人们不能只是在域之间随机创建Ajax请求,因为这是一个安全问题。

如果你绝对需要从不同的域获取内容,我会考虑使用cURL创建你自己的服务器API,在同一个域上提供你自己的内容,然后在那里使用Ajax。否则,你将不得不看看谷歌是否会授予CORS访问权限,或者是否有某种内置的JSONP请求。