如何查看 XmlHttpRequest 的问题所在

How To See What The Problem Is With XmlHttpRequest

我在 ASP.NET 中写了一个简单的 REST API returns 一些 json 格式的数据。然后我尝试写一些 javascript 来使用它,但碰壁了。当我使用演示 API 时,我的代码工作正常,但是当我尝试使用我自己的 API 时,它失败了,我不知道如何获取有关原因的任何信息。这是我演示问题的代码(html 和 javascript):

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
        <meta http-equiv="Pragma" content="no-cache" />
        <meta http-equiv="Expires" content="0" />
    </head>
    <body>
        <h2>Test Output:</h2>
        <div id="testOutput"></div>
    </body>
    
    <script language="javascript">
        function listAllProperties(o) {
            var objectToInspect;     
            var result = [];
        
            for(objectToInspect = o; objectToInspect !== null; 
                   objectToInspect = Object.getPrototypeOf(objectToInspect)) {  
                result = result.concat(
                    Object.getOwnPropertyNames(objectToInspect)
                );  
            }
        
            return result; 
        }
    </script>
    <script language="javascript">
        const testOutput = document.getElementById('testOutput')
    
        var request = new XMLHttpRequest()
        request.open('GET', 'https://ghibliapi.herokuapp.com/films', true)  // with this line, "In Function" is printed
        //request.open('GET', 'http://local.api.com/moviesearch/crash', true)  // ...but if you use this line instead, "In Function" is NOT printed
        request.onload = function () {
            testOutput.innerHTML = "In Function with https://ghibliapi.herokuapp.com/films <br /><br />"
        }
        request.send()
    
        var request2 = new XMLHttpRequest()
        request2.open('GET', 'http://local.api.com/moviesearch/crash', true)  // As stated in the comment above, "In Function" is NOT printed
        request2.onload = function () {
            testOutput.innerHTML += "In Function with http://local.api.com/moviesearch/crash <br /><br />"
        }
    
        function handleEvent(progressEventObject) {
            testOutput.innerHTML += "Failed with http://local.api.com/moviesearch/crash <br /><br />"
            testOutput.innerHTML += "<b>Error Details</b> <br /><br />"
            listAllProperties(progressEventObject).forEach((prop) => testOutput.innerHTML += `${prop} = ${progressEventObject[prop]}<br /><br />`);
            testOutput.innerHTML += "<b>Request Details</b> <br /><br />"
            listAllProperties(progressEventObject.currentTarget).forEach((prop) => testOutput.innerHTML += `${prop} = ${progressEventObject[prop]}<br /><br />`);
        }
    
        request2.addEventListener('error', handleEvent);
        request2.send()
    </script>
    </html>

在“var request = new XMLHttpRequest()”之后的第一段代码中,您可以看到我正在使用位于“https://ghibliapi.herokuapp.[=35] 的演示 API =]”,这很有效,但是你可以在下面看到“request2”我尝试使用我自己的 API(运行 在我使用 IIS 的本地机器上,我可以在本地访问 http://local.api.com/moviesearch/{searchTerm}).在监视对我写的 API 的请求时,使用 Firefox 开发人员工具中的“网络”选项卡,我看不出响应有什么问题(原始响应在此处粘贴 headers)。

HTTP/1.1 200 OK
Cache-Control: no-cache
Pragma: no-cache
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/10.0
X-AspNet-Version: 4.0.30319
X-Powered-By: ASP.NET
Date: Tue, 24 Nov 2020 01:11:12 GMT
Content-Length: 69

{"Count":1,"ItemList":["Wedding Crashers 2005 Uncorked Edition"]}

根据 Firefox 开发人员工具中的网络选项卡,此响应在等待 286 毫秒后返回。

我在 print-out 的 progressEvent object 或 XmlHttpRequest object 中看不到任何有用的东西我在 javascript 的结尾做了(但我会粘贴下面的输出有助于调试。

错误详情:

"isTrusted" = "true"
"lengthComputable" = "false"
"loaded" = "0"
"total" = "0"
"constructor" = "function ProgressEvent() { [native code] }"
"composedPath" = "function composedPath() { [native code] }"
"stopPropagation" = "function stopPropagation() { [native code] }"
"stopImmediatePropagation" = "function stopImmediatePropagation() { [native code] }"
"preventDefault" = "function preventDefault() { [native code] }"
"initEvent" = "function initEvent() { [native code] }"
"type" = "error"
"target" = "[object XMLHttpRequest]"
"srcElement" = "[object XMLHttpRequest]"
"currentTarget" = "[object XMLHttpRequest]"
"eventPhase" = "2"
"bubbles" = "false"
"cancelable" = "false"
"returnValue" = "true"
"defaultPrevented" = "false"
"composed" = "false"
"timeStamp" = "382"
"cancelBubble" = "false"
"originalTarget" = "[object XMLHttpRequest]"
"explicitOriginalTarget" = "[object XMLHttpRequest]"
"NONE" = "0"
"CAPTURING_PHASE" = "1"
"AT_TARGET" = "2"
"BUBBLING_PHASE" = "3"
"ALT_MASK" = "1"
"CONTROL_MASK" = "2"
"SHIFT_MASK" = "4"
"META_MASK" = "8"
"constructor" = "function ProgressEvent() { [native code] }"
"toString" = "function toString() { [native code] }"
"toLocaleString" = "function toLocaleString() { [native code] }"
"valueOf" = "function valueOf() { [native code] }"
"hasOwnProperty" = "function hasOwnProperty() { [native code] }"
"isPrototypeOf" = "function isPrototypeOf() { [native code] }"
"propertyIsEnumerable" = "function propertyIsEnumerable() { [native code] }"
"__defineGetter__" = "function __defineGetter__() { [native code] }"
"__defineSetter__" = "function __defineSetter__() { [native code] }"
"__lookupGetter__" = "function __lookupGetter__() { [native code] }"
"__lookupSetter__" = "function __lookupSetter__() { [native code] }"
"__proto__" = "[object ProgressEvent]"
"constructor" = "function ProgressEvent() { [native code] }"

请求详细信息:

"open" = "undefined"
"setRequestHeader" = "undefined"
"send" = "undefined"
"abort" = "undefined"
"getResponseHeader" = "undefined"
"getAllResponseHeaders" = "undefined"
"overrideMimeType" = "undefined"
"onreadystatechange" = "undefined"
"readyState" = "undefined"
"timeout" = "undefined"
"withCredentials" = "undefined"
"upload" = "undefined"
"responseURL" = "undefined"
"status" = "undefined"
"statusText" = "undefined"
"responseType" = "undefined"
"response" = "undefined"
"responseText" = "undefined"
"responseXML" = "undefined"
"mozAnon" = "undefined"
"mozSystem" = "undefined"
"UNSENT" = "undefined"
"OPENED" = "undefined"
"HEADERS_RECEIVED" = "undefined"
"LOADING" = "undefined"
"DONE" = "undefined"
"constructor" = "function ProgressEvent() { [native code] }"
"onloadstart" = "undefined"
"onprogress" = "undefined"
"onabort" = "undefined"
"onerror" = "undefined"
"onload" = "undefined"
"ontimeout" = "undefined"
"onloadend" = "undefined"
"constructor" = "function ProgressEvent() { [native code] }"
"addEventListener" = "undefined"
"removeEventListener" = "undefined"
"dispatchEvent" = "undefined"
"constructor" = "function ProgressEvent() { [native code] }"
"toString" = "function toString() { [native code] }"
"toLocaleString" = "function toLocaleString() { [native code] }"
"valueOf" = "function valueOf() { [native code] }"
"hasOwnProperty" = "function hasOwnProperty() { [native code] }"
"isPrototypeOf" = "function isPrototypeOf() { [native code] }"
"propertyIsEnumerable" = "function propertyIsEnumerable() { [native code] }"
"__defineGetter__" = "function __defineGetter__() { [native code] }"
"__defineSetter__" = "function __defineSetter__() { [native code] }"
"__lookupGetter__" = "function __lookupGetter__() { [native code] }"
"__lookupSetter__" = "function __lookupSetter__() { [native code] }"
"__proto__" = "[object ProgressEvent]"
"constructor" = "function ProgressEvent() { [native code] }"

最后,当对我的 API 的请求导致错误事件侦听器函数被调用时,我没有看到任何内容被写入浏览器控制台。

感谢您抽出宝贵时间阅读本文,以及您可以给我的有关如何继续的任何提示。

正如 Bravo 在他们的评论中所建议的,我检查了开发工具控制台并看到了 CORS 错误:

"Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at localhost/moviesearch/crash. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing)."

下面post的答案是这个问题的真正awesome/easy解决方案: Setting Access-Control-Allow-Origin in ASP.Net MVC - simplest possible method

谢谢你,太棒了!