Trạng thái XMLHttpRequest 0 (responseText trống)


104

Không thể lấy dữ liệu với XMLHttpRequest (trạng thái 0 và responseText trống):

xmlhttp = new XMLHttpRequest ();
xmlhttp.open ("GET", "http://www.w3schools.com/XML/cd_catalog.xml", true);
xmlhttp.onreadystatechange = function () 
{
  if (xmlhttp.readyState == 4)
    alert ("trạng thái" + xmlhttp.status);
}
xmlhttp.send ();

Nó cảnh báo "trạng thái 0".

Trường hợp tương tự với yêu cầu localhost (cd_catalog.xml được lưu dưới dạng tệp cục bộ)

xmlhttp.open ("GET", "http: //localhost/cd_catalog.xml", true);

Nhưng với yêu cầu IP localhost

xmlhttp.open ("GET", "http://127.0.0.1/cd_catalog.xml", true);

và với yêu cầu tệp cục bộ

xmlhttp.open ("GET", "cd_catalog.xml", true);

mọi thứ đều ổn (trạng thái 200)

Điều gì có thể gây ra sự cố (trạng thái = 0) với yêu cầu trực tuyến?

PS: Tiêu đề HTTP trực tiếp cho thấy mọi thứ đều ổn trong cả 4 trường hợp:

  HTTP / 1.1 200 OK
  Nội dung-Độ dài: 4742

PS2: Máy chủ web cục bộ Apache trên VMWare (máy chủ lưu trữ hệ điều hành Win7, hệ điều hành khách Ubuntu, bộ điều hợp mạng - NAT). Trình duyệt - Firefox.


1
Trang thử nghiệm của bạn http://127.0.0.1có ngẫu nhiên không? ;)
Roatin Marth

Đúng. <code> 127.0.0.1/CDCatalogTest.html </code>
arigasa

7
Bạn đã trả lời câu hỏi của bạn. XMLHttpRequestkhông thể thực hiện các yêu cầu tên miền chéo. Tuy nhiên, có một số cách giải quyết. Hãy xem jquery chẳng hạn.
meze

Sử dụng php để lấy tệp. Ít công việc xung quanh: jquery-howto.blogspot.com/2009/04/...

2
@meze: Lệnh gọi tên miền chéo hoạt động với jQuery. Nhưng làm thế nào nó có thể không hoạt động với JavaScript thuần túy, vì jQuery được triển khai trong JavaScript? Nó làm cho không có ý nghĩa với tôi. Có phải jQuery đang sử dụng một số cách giải quyết khó chịu không?
Gruber

Câu trả lời:


55

trạng thái là 0 khi tệp html của bạn có chứa tập lệnh được mở trong trình duyệt thông qua lược đồ tệp. Đảm bảo đặt các tệp trong máy chủ của bạn (apache hoặc tomcat gì đó) và sau đó mở nó qua giao thức http trong trình duyệt. (tức là http: //localhost/myfile.html ) Đây là giải pháp.


1
Tại sao điều này lại bị từ chối? Nó thực sự là sự thật! Yêu cầu XHR từ tệp: // URL của tệp cũng có trong tệp: // URL thực sự có trạng thái == 0 khi thành công (đã thử nghiệm trên FF 24.0.5).
Daniel Roethlisberger,

3
Tôi cũng nhận được trạng thái == 0 về thành công trên Safari Phiên bản 6.1.6.
Planar

Tôi đang gặp tình trạng = 0 (nhưng tình trạng 200 trên mạng) sử dụng tải tạm thời add-on trên firefox
JobaDiniz

1
câu trả lời vẫn hợp lệ. Phản hồi HTTP là 200 đối với các lược đồ từ xa thực tế (http và cộng sự) và 0 đối với tệp cục bộ ( file://lược đồ). Rõ ràng, trước tiên bạn cần cho phép tải tệp cục bộ bằng cách tắt CORS.
pid

31

Nguyên nhân của sự cố của bạn là bạn đang cố thực hiện cuộc gọi giữa nhiều miền và nó không thành công .

Nếu bạn đang phát triển localhost, bạn có thể thực hiện các cuộc gọi giữa nhiều miền - tôi làm việc đó mọi lúc.

Đối với Firefox, bạn phải bật nó trong cài đặt cấu hình của mình

signed.applets.codebase_principal_support = true

Sau đó, thêm một cái gì đó như thế này vào mã mở XHR của bạn:

  if (isLocalHost()){
    if (typeof(netscape) != 'undefined' && typeof(netscape.security) != 'undefined'){
      netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
    }
  }

Đối với IE, nếu tôi nhớ đúng, tất cả những gì bạn phải làm là bật cài đặt Bảo mật của trình duyệt trong "Khác → Truy cập nguồn dữ liệu trên các miền" để nó hoạt động với ActiveX XHRs.

IE8 trở lên cũng đã thêm các khả năng miền chéo cho các đối tượng XmlHttpRequest gốc, nhưng tôi chưa chơi với chúng.


8
Trong trường hợp bất cứ ai cần nó, dành cho Chrome, bạn cần phải khởi động một thể hiện mới của nó (mà không cần bất kỳ đã được mở) và sử dụng--allow-file-access-from-files
TheZ

@TheZ: Bạn có 100% không? Tôi nghe nói rằng bạn chỉ cần chạy phiên bản Chrome mới, có --allow-file-access-from-filesnút chuyển, nhưng bạn không phải đóng tất cả các phiên bản đang chạy khác. Chính xác như trong trường hợp Chế độ ẩn danh của Chrome - bạn có thể sử dụng nó mà không cần đóng bất kỳ phiên bản đang chạy nào khác.
trejder

Có vẻ như hỗ trợ cho 'UniversalBrowserRead' đã bị loại bỏ, vì vậy công việc này không phải là một tùy chọn.
perilandmishap

Ngoài ra, nó có thể xảy ra khi bạn yêu cầu trang http từ trang https (như tiện ích mở rộng trong trình duyệt).
sibvic

Tôi đang gặp sự cố này, mặc dù trang html và tập lệnh AJAX nằm trong cùng một miền. Nhưng thật kỳ lạ, nó chỉ ảnh hưởng đến một số tập lệnh, đáng chú ý nhất là bất kỳ tập lệnh nào truy cập tài nguyên MongoDB. Bất kỳ manh mối tại sao điều này là?
David Edwards

26

Trên thực tế, hãy đảm bảo rằng loại nút của bạn là Nút không phải Gửi, điều này đã gây ra xung đột trạng thái ở nơi tôi gặp gần đây.


1
Có một xung đột vì việc gửi biểu mẫu có một số hành vi mặc định mà bạn cần phải ngăn chặn nếu bạn đang xử lý sự kiện và tự thực hiện cuộc gọi ajax. Bạn có thể ngăn hành vi mặc định bằng cách lấy sự kiện trong trình xử lý của mình và gọie.preventDefault()
Jordan

20

Nếu máy chủ phản hồi phương thức OPTIONS và NHẬN và ĐĂNG (bất kỳ phương thức nào bạn đang sử dụng) với tiêu đề như:

Access-Control-Allow-Origin: *

Nó có thể hoạt động tốt. Có vẻ như trong FireFox 3.5 và rekonq 0.4.0. Rõ ràng, với tiêu đề đó và phản hồi ban đầu cho OPTIONS, máy chủ đang nói với trình duyệt, "Hãy tiếp tục và để yêu cầu tên miền chéo này được thực hiện".


3
Đây là câu trả lời đúng! Hãy xem en.wikipedia.org/wiki/Cross-origin_resource_sharing để biết thêm thông tin. Nếu bạn thêm tiêu đề này, nó không phải là "có thể hoạt động", mà là "sẽ hoạt động". NB Những gì bạn cần thêm là một HTTP / response / header - vì vậy bạn chỉ có thể thực hiện việc này trên máy chủ mà bạn kiểm soát. Sẽ không bao giờ có thể trực tiếp tìm nạp w3schools.com/XML/cd_catalog.xml bằng cách sử dụng XMLHttpRequest(tức là theo câu hỏi ban đầu), vì tài nguyên đó không (ít nhất là vào ngày 24 tháng 4 năm 2015) bao gồm bất kỳ tiêu đề CORS nào như vậy.
MikeBeaton

13

Cũng xem xét thời gian chờ yêu cầu :

Trình duyệt hiện đại trả về readyState = 4 và s tatus = 0 nếu có quá nhiều thời gian trước khi máy chủ phản hồi.


3
@AndreaSavojardo: Bạn có bất kỳ tài liệu tham khảo nào (như một bài đăng trên MDN) về việc liệu hành vi này có tuân thủ các tiêu chuẩn không?
Alexander Abakumov

@AndreaSavojardo Tôi có readyState = 4 và status = 0 và máy chủ không chạy nhưng cảnh báo lỗi hiển thị cho tôi nhanh .... bao nhiêu thời gian trôi qua cho "yêu cầu hết thời gian"?

7

Thêm vào setRequestHeader("Access-Control-Allow-Origin","*")phản hồi máy chủ của bạn.


3

Tôi đã phải đối mặt với một vấn đề tương tự. Mọi thứ đều ổn, "readystate" là 4, nhưng "status" là 0. Đó là do tôi đang sử dụng máy chủ di động Apache PHP và tệp của tôi trong đó tôi sử dụng đối tượng "XMLHttpRequest" là tệp html. Tôi đã thay đổi phần mở rộng tệp thành php và vấn đề đã được giải quyết.


3

Mở bảng điều khiển javascript . Bạn sẽ thấy một thông báo lỗi ở đó. Trong trường hợp của tôi, đó là CORS.


2

Để trả lời câu hỏi tại sao http://127.0.0.1/cd_catalog.xmlhoạt động trong khi http://localhost/cd_catalog.xmlkhông hoạt động : Firefox đang coi 127.0.0.1 và localhost là hai miền khác nhau.


2

Để xem vấn đề là gì, khi bạn gặp lỗi khó hiểu 0, hãy truy cập ... | Các công cụ khác | Công cụ nhà phát triển (Ctrl + Shift + I) trong Chrome (trên trang báo lỗi)

Đọc văn bản màu đỏ trong nhật ký để nhận thông báo lỗi thực sự. Nếu có quá nhiều thứ trong đó, hãy nhấp chuột phải và Clear Console, sau đó thực hiện lại yêu cầu cuối cùng của bạn.

Vấn đề đầu tiên của tôi là, lần đầu tiên tôi chuyển tiêu đề Ủy quyền tới dịch vụ web miền chéo của riêng tôi cho trình duyệt.

Tôi đã có:

Access-Control-Allow-Origin: *

Nhưng không:

Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Authorization

trong tiêu đề phản hồi của dịch vụ web của tôi.

Sau khi tôi thêm điều đó, lỗi 0 của tôi đã biến mất khỏi máy chủ web của riêng tôi, cũng như khi chạy tệp index.html cục bộ mà không có máy chủ web, nhưng vẫn xuất hiện lỗi trong bút mã.

Quay lại ... | Các công cụ khác | Công cụ dành cho nhà phát triển trong khi gặp lỗi trong codepen và có giải thích rõ ràng: codepen sử dụng https, vì vậy tôi không thể thực hiện cuộc gọi tới http vì tính bảo mật thấp hơn.

Do đó, tôi cần lưu trữ dịch vụ web của mình trên https.

Biết cách nhận được thông báo lỗi thực sự - vô giá!


Tôi đã sử dụng cách tiếp cận này (f12 trong chrome) và phát hiện ra rằng tôi đang cố gắng chuyển từ https sang http nhưng bị lỗi một cách âm thầm mà không cung cấp bất kỳ điều gì hữu ích. THÔNG ĐIỆP LỖI: Nội dung hỗn hợp VM1152: 1: Trang tại 'https://mysiteoriginsite' được tải qua HTTPS, nhưng đã yêu cầu điểm cuối XMLHttpRequest không an toàn 'http://MyDestinationSite/MyService.svc'. Yêu cầu này đã bị chặn; nội dung phải được phân phát qua HTTPS.
GreyDwarf

1

Đây là một trường hợp khác trong đó status === 0, cụ thể cho việc tải lên:

Nếu bạn đính kèm một 'load'trình xử lý sự kiện XHR.upload, như đề xuất của MDN (cuộn xuống phần tải lên của 'Tiến trình giám sát'), đối tượng XHR sẽ có status=0và tất cả các thuộc tính khác sẽ là chuỗi trống. Nếu bạn đính kèm 'load'trình xử lý trực tiếp vào đối tượng XHR, giống như khi tải xuống nội dung, bạn sẽ ổn (vì bạn không chạy khỏi localhost).

Tuy nhiên, nếu bạn muốn nhận được dữ liệu tốt trong 'progress'trình xử lý sự kiện của mình , bạn cần phải đính kèm trình xử lý XHR.upload, không phải trực tiếp vào chính đối tượng XHR.

Tôi chỉ mới thử nghiệm điều này cho đến nay trên Chrome OSX, vì vậy tôi không chắc vấn đề ở đây là tài liệu của MDN và mức độ triển khai của Chrome ...


1

Alex Robinson đã (và đầu tiên) đưa ra câu trả lời chính xác cho vấn đề này. Nhưng để giải thích kỹ hơn một chút ...

Bạn phải thêm tiêu đề phản hồi HTTP:

Access-Control-Allow-Origin: *

Nếu bạn làm điều này, kết quả không chỉ là "có thể hoạt động", mà là "sẽ hoạt động".

NB Những gì bạn cần thêm là một tiêu đề phản hồi HTTP - vì vậy bạn chỉ có thể thực hiện việc này trên máy chủ mà bạn kiểm soát. Sẽ không bao giờ có thể tìm nạp trực tiếp http://w3schools.com/XML/cd_catalog.xml từ URL ban đầu của nó bằng cách sử dụng XMLHttpRequest(theo câu hỏi của OP), vì tài nguyên đó không (ít nhất, không phải là ngày 24 tháng 4 năm 2015) bao gồm bất kỳ tiêu đề CORS nào như vậy.

http://en.wikipedia.org/wiki/Cross-origin_resource_sharing cung cấp thêm thông tin.


0

Vấn đề tương tự như điều này của tôi đã được giải quyết bằng cách kiểm tra mã html của tôi. Tôi đã có một onclicktrình xử lý trong nút gửi biểu mẫu của tôi tới một phương thức. như thế này: onclick="sendFalconRequestWithHeaders()". Phương pháp này lần lượt gọi ajax giống như của bạn và thực hiện những gì tôi muốn. Nhưng không như mong đợi, trình duyệt của tôi không trả lại gì.

Học được từ sự chăm chỉ của ai đó , tôi đã trả về false trong trình xử lý này và giải quyết. Hãy để tôi đề cập rằng trước khi đến với bài đăng này, tôi đã dành toàn bộ 3 ngày cuối tuần và nửa ngày trong văn phòng để viết mã triển khai CORS filters, jetty configvà những jersey and embedded jettythứ liên quan khác - chỉ để sửa lỗi này, xoay quanh tất cả sự hiểu biết của tôi xung quanh cross domain ajax requestsvà những thứ tiêu chuẩn. Thật nực cười khi những lỗi đơn giản trong javascript lại khiến bạn chết lặng.

Thành thật mà nói, tôi đã thử signed.applets.codebase_principal_support = truevà viết isLocalHost() **if**. Có thể phương pháp này cần được chúng tôi thực hiện, firefox nói rằng không có như vậy Bây giờ tôi phải xóa mã của mình để gửi bản vá git một cách sạch sẽ. Nhờ ai đó.


0

Yêu cầu trình duyệt "127.0.0.1/somefile.html" không thay đổi đối với máy chủ web cục bộ, trong khi "localhost / somefile.html" có thể đến dưới dạng "0: 0: 0: 0: 0: 0: 0: 1 / somefile.html "nếu IPv6 được hỗ trợ. Vì vậy, sau này có thể được xử lý như đi từ miền này sang miền khác.


0

Alex Robinson và bmju đã cung cấp thông tin có giá trị để hiểu các vấn đề về nguồn gốc chéo. Tôi muốn nói thêm rằng bạn có thể cần thực hiện cuộc gọi OPTIONS rõ ràng trong mã khách hàng của mình trước khi thực hiện GET / POST mong muốn (ví dụ: đối với điểm cuối dịch vụ CORS OAuth). Trình duyệt / thư viện của bạn có thể không tự động xử lý yêu cầu OPTIONS. Gruber, đây là một trong những câu trả lời có thể cho câu hỏi của bạn.


0

Tôi đã gặp vấn đề tương tự (readyState là 4 và trạng thái 0) , sau đó tôi làm theo một cách tiếp cận khác được giải thích trong hướng dẫn này: https://spring.io/guides/gs/consuming-rest-jquery/

Anh ấy hoàn toàn không sử dụng XMLHttpRequest , thay vào đó anh ấy sử dụng phương thức jquery $ .ajax () :

<head>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    <script src="hello.js"></script>
</head>

<body>
    <div>
        <p class="greeting-id">The ID is </p>
        <p class="greeting-content">The content is </p>
    </div>
</body>

và đối với tệp public / hello.js (hoặc bạn có thể chèn trực tiếp nó vào cùng một mã HTML):

$(document).ready(function() 
 {
    $.ajax({
        url: "http://rest-service.guides.spring.io/greeting"
   }).then(function(data) {
      $('.greeting-id').append(data.id);
      $('.greeting-content').append(data.content);
   });
 });

2
Bạn có nhận ra rằng jQuery $.ajax()sử dụng XMLHttpRequestbên trong, phải không?
Manngo

0

Tôi đã phải thêm địa chỉ IP hiện tại của mình (một lần nữa) vào danh sách trắng của Atlas MongoDB và do đó đã loại bỏ lỗi trạng thái 0 của XMLHttpRequest


-1

Tôi chỉ gặp sự cố này vì tôi đã sử dụng 0.0.0.0làm máy chủ của mình, đã thay đổi nó thành localhostvà nó hoạt động.


-4

Chỉnh sửa: Vui lòng đọc bình luận của Malvolio bên dưới vì kiến ​​thức của câu trả lời này đã lỗi thời.

Bạn không thể thực hiện XMLHttpRequests trên nhiều miền.

Lời gọi 127.0.0.1hoạt động vì trang thử nghiệm của bạn được đặt tại 127.0.0.1và thử nghiệm cục bộ cũng hoạt động vì ... đó là thử nghiệm cục bộ.

Hai thử nghiệm khác không thành công vì JavaScript không thể giao tiếp với máy chủ ở xa thông qua XMLHttpRequest.

Thay vào đó, bạn có thể cân nhắc:

  • XMLHttp-yêu cầu máy chủ của riêng bạn tìm nạp nội dung XML từ xa cho bạn (ví dụ: tập lệnh php)
  • Cố gắng sử dụng một dịch vụ như GoogleAppEngine nếu bạn muốn giữ nó đầy đủ JavaScript.

Hy vọng rằng sẽ giúp


40
Điều này chỉ là sai. Bạn có thể thực hiện các XMLHttpRequests trên nhiều miền.
Malvolio

1
"Bạn có thể không" như trong "Bạn không nên làm điều đó bởi vì nó không bao giờ là một ý tưởng tốt"
Gabriel Sprenger

24
- đủ công bằng, nhưng tôi không biết liệu một bình luận có phải là diễn đàn tốt nhất cho việc đó hay không. XMLHttpRequests đa miền chắc chắn có một số thách thức về bảo mật nhưng chúng cung cấp tất cả các công cụ cần thiết để đối phó với những thách thức đó. Bên cạnh đó, chúng cho phép các trang web cung cấp dịch vụ cho các trang web khác một cách dễ dàng, sử dụng CDN để truyền dữ liệu và phản hồi nhanh hơn các yêu cầu của người dùng. Nếu bạn có bất kỳ câu hỏi cụ thể nào, bạn có thể nhắn tin cho tôi, hoặc tốt hơn, đăng câu hỏi tại đây trên SO và thu hút sự chú ý của tôi.
Malvolio

2
@GabrielSprenger: Cross-miền XMLHttpRequestcủa không chỉ một tốt ý tưởng, nó rất phổ biến hiện nay mà không làm cho họ trong một ứng dụng web hiện đại (ngoài một số loại HelloWorlds) là một cái gì đó vô lý. Mọi dịch vụ REST bên ngoài mà ứng dụng của bạn sử dụng đều yêu cầu miền chéo XMLHttpRequest. Và đó là lý do tại sao tất cả những thứ CORS đó được thêm vào.
Alexander Abakumov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.