gpt4 book ai didi

javascript - XHR 响应回调中数据错误

转载 作者:行者123 更新时间:2023-12-03 04:49:29 24 4
gpt4 key购买 nike

我目前正在尝试编写一个简单的应用程序,它通过多个异步 xhr 请求从服务器请求数据。响应在每个请求的 onreadystatechanged 回调中处理。

目前,如果我异步执行超过 10 个请求,我就会开始从请求回调中获取错误的数据,即:

book 1: abc --> correct
book 2: efg --> correct
book 3: efg --> wrong
book 4: kjl --> correct

我回到了 onreadystatehandler,即使在这里请求对象也包含错误的数据( req.responseText )。url (req.responseURL) 是正确的,因为每个请求的 url 都会被回调一次,只是数据错误。

因此,我在浏览器开发工具中查看了收到的响应,以验证确实从服务器给出了正确的数据,情况就是如此。

老实说,我不知道如何解决这个问题,因为服务器正在响应正确的数据,但请求回调只是“使用”错误的数据,即使具有正确的网址。

这就是我尝试实现它的方法:

var sendRequest = function(url, callback){
var req = new XMLHttpRequest();
req.overrideMimeType('text/plain');
req.open("GET", url, true);
if(callback) {
req.onreadystatechange = (function(req,callback){
return function() {
if(req.readyState == 4) {
if(req.status == 200 || req.status == 304) {

var response;
try {
response = JSON.parse(req.responseText);
} catch(error) {
callback(undefined, req.responseText);
return;
}

if(response.error)
callback(response.error, response);
else
callback(undefined, response);

}else{
callback("Error", req.responseText)
}
}
};
})(req,callback);
}
req.send(params);
}

这是我用于发送请求的代码示例。

var booksToLoad = 0;
for(var i = 0; i < libraries.length; i++) {
(function(i) {
sendRequest('/LibraryList?'+'Id='+libraries[i]._id, function(err, response) {
libraries[i] = response.library;
booksToload += libraries[i].books.length;
for(var j=0; j < libraries[i].books.length; j++) {
(function (i, j) {
sendRequest('/BookList?'+'Id='+libraries[i].books[j]._id, function (err, response) {
libraries[i].books[j].pages = response.pages;
--booksToLoad;
if(booksToLoad == 0)
return;
});
})(i, j);
}
});
})(i);
}

我尝试过的事情:

  1. 将 for 循环转变为递归调用 --> 可以,但速度很慢。
  2. 将请求存储在数组中并迭代发送 --> 不起作用
  3. 检查 JSON.parse() 是否以某种方式破坏它 --> 不,纯数据也错误
  4. 强制不使用 header 进行缓存 --> 不起作用
  5. 尝试了不同的浏览器(chrome + firefox)--> 不起作用

如前所述,我对以下事实感到困惑:来自服务器的数据很好,并且使用正确的 req.responseURL 调用回调,但使用错误的数据(不是从响应中的 url 获取)。

感谢您的帮助,我在这里不知所措......

马吉斯特罗

<小时/>

编辑:我有点放弃了,并认为发送如此数量的 xhr 请求无论如何都是糟糕的设计。所以我将请求捆绑在一起(整个图书馆一次,包含书籍+页面)。

这样,如果包稍后变大,我将被迫管理我请求的数据(我可以完全控制),而不是浏览器允许的请求量。

不知道这是否是个好主意,但我不能在这个问题上浪费更多时间。还是想知道到底是什么原因导致了这种行为,以供将来引用。

感谢您的宝贵时间,

马吉斯特罗

最佳答案

试试这个:

function fetchLibrary(i){
sendRequest('/LibraryList?Id='+libraries[i]._id, function(err, response) {
libraries[i] = response.library;
for(var j=0; j < libraries[i].books.length; j++)
fetchBooks(i,j);
});
}

function fetchBooks(i,j){
sendRequest('/BookList?Id='+libraries[i].books[j]._id, function (err, response) {
libraries[i].books[j].pages = response.pages;
});
}

for(var i = 0; i < libraries.length; i++) {
fetchLibrary(i);
}

并且,使用网络选项卡确保发送的请求确实返回正确的结果。如果没有(检查响应),请修复您的服务器端获取组件。

==========

好的,这里是服务器端和客户端组件的经过全面测试的功能示例。以此作为引用:

服务器端(service.php):

<?php


$libraries = [
["id" => 1, "name" => "foo"],
["id" => 2, "name" => "bar"],
["id" => 3, "name" => "baz"]
];

$books = [
["library_id" => 1, "id" => 1, "pages" => 10],
["library_id" => 1, "id" => 2, "pages" => 11],
["library_id" => 1, "id" => 3, "pages" => 12],
["library_id" => 2, "id" => 4, "pages" => 13],
["library_id" => 2, "id" => 4, "pages" => 14],
["library_id" => 2, "id" => 5, "pages" => 15],
["library_id" => 3, "id" => 6, "pages" => 16],
["library_id" => 3, "id" => 7, "pages" => 17],
["library_id" => 3, "id" => 8, "pages" => 18]
];
header("Content-type: application/json;encoding=utf-8");
if (!isset($_REQUEST["request_id"])){
$protocol = (isset($_SERVER['SERVER_PROTOCOL']) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0');
header($protocol . ' 500 Error - Specify Request ID');
exit;
}
$request_id = $_REQUEST["request_id"];
$library_id = isset($_REQUEST["library_id"])?$_REQUEST["library_id"]:null;

$ret = [];
if ($library_id){
// fetch list of books for the library_id
foreach ($books as $book){
if ($book["library_id"] == $library_id){
$ret[] = $book;
}
}
} else {
// fetch list of libraries
$ret = $libraries;
}
print_r(json_encode(["request_id" => $request_id, "result" => $ret], JSON_PRETTY_PRINT));

客户端:

<script>
function r(url, callback){
var req = new XMLHttpRequest();
req.responseType = "json";
url += url.match(/\?/)?"&":"?";
var request_id = new Date().getTime();
url += "request_id=" + request_id;
req.open("GET", url, true);
req.onreadystatechange = function(){
if (req.readyState == 4) {
status = req.status;
if (status == 200) {
console.log("URL " + url + " received", req.response);
callback(req.response, request_id);
} else {
window.alert("Problem with request " + url);
console.error(url + " failed. Status: " + status);
console.log(req.response);
}
}
}
req.send();
}

function fetchLibraries(){
r("service.php", function(data, id){
for (var x in data.result){
fetchBooks(data.result[x]);
}
});
}

function fetchBooks(library){
var e = document.createElement("p");
document.body.appendChild(e);
e.innerHTML = "loading " + library.id;
r("service.php?library_id=" + library.id, function(data){
e.innerHTML = "";
for (var x in data.result){
var book = data.result[x];
e.innerHTML += "Book: " + book.id + ", pages: " + book.pages + "<br>";
}
});
}

fetchLibraries();
</script>

经过充分测试,工作完美。

关于javascript - XHR 响应回调中数据错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42720672/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com