【问题标题】:How can I run ajax for an array of objects?如何为对象数组运行 ajax?
【发布时间】:2016-06-14 22:50:28
【问题描述】:

我不确定这是否是使用 ajax 的有效方式,但我正在使用 for 循环遍历一组信息:

loadProfiles.js

var tempString = "";
var searchPeople = function(sv){
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function(){
        if(xhttp.readyState == 4 && xhttp.status == 200){
            tempString = xhttp.responseText;
            loadPeople(tempString, sv);
        }
    }

    var searchvalue = sv;
    searchvalue = searchvalue.join(" ");

    xhttp.open("GET", "php/searchProfiles.php?searchvalue=" + searchvalue, true);
    xhttp.send();
}

var loadPeople = function(people, sv){
    loadedPeople = [];
    var normList = people.split(",");
    var list = people.toLowerCase().split(",");
    list.splice(list.length - 1, 1);
    var zsearch = sv;
    for(var i = 0; i < list.length; i++){
        loadedImageId[i] = list[i].split("_")[1];
        if(loadedImageId[i] == 0){
            loadedImageId[i] = "images/GrayProfilePic.png";
        }
        else{///////////////////////////////////This is what I need to fix
            var grabPic = new XMLHttpRequest();
            grabPic.onreadystatechange = function(){
                if(grabPic.readyState == 4 && grabPic.status == 200){
                    console.log("ready to go");
                    loadedImageId[i] = grabPic.responseText;
                    if(loadedImageId[i] == "Error1"){
                        loadedImageId[i] = "images/GrayProfilePic.png";
                    }
                }
            }

            grabPic.open("GET", "php/grabProfPics.php?imageid=" + loadedImageId[i], true);
            grabPic.send();
        }//////////////////////////////////////////////
        list[i] = list[i].split("_")[0];
        for(var j = 0; j < zsearch.length; j++){
            if(list[i].indexOf(zsearch[j]) > -1){
                if(loadedPeople.indexOf(list[i]) == -1){
                    if(loadedPeople.indexOf(normList[i].split("_")[0]) == -1){
                        loadedPeople.push(normList[i].split("_")[0]);
                    }
                }
            }
        }
    }
    console.log(loadedPeople);
    console.log(loadedImageId);

}

searchProfiles.php

$query = "SELECT username, imageid FROM `memberHandler`";
    $result = mysqli_query($connect, $query) or die("Could not query");
    while($row = mysqli_fetch_assoc($result)){
        echo $row['username'] . "_" . $row['imageid'] . ",";
    }

grabProfPics.php

$query = "SELECT image, mime_type FROM memberProfilePictures WHERE `id`='$imageid'";
    $result = mysqli_query($connect, $query);
    if(mysqli_num_rows($result) != 0){
        $row = mysqli_fetch_assoc($result);

        $imagesrc = $row['image'];
        $imagesrc = base64_encode($imagesrc);
        $imagetype = $row['mime_type'];

        echo "data:" . $imagetype . ";base64," . $imagesrc . "";
    }
    else{
        echo "Error1";
    }

但是服务器需要一些时间来发送它的返回码,此时 for 循环中的变量 i 早已被更改。有没有办法有效地做到这一点,并根据当前数组值用新信息更新数组?我希望这个问题是有道理的!感谢您的帮助 =)

基本上我正在尝试遍历图像 id,如果 id 不为零(意味着他们已经为他们的个人资料设置了图像-否则他们没有并且 id 为 0)然后它将使用 ajax 来连接到图像数据库,获取与特定 ID 相关的图像,然后返回图像源并更新数组。很抱歉,在我想我可以使用更简化的版本之前,我没有更具体地说明这一点。

【问题讨论】:

  • 这不是一种有效的方法,您应该采用另一种方法。
  • 您处理此问题的方法存在根本缺陷。您正在尝试同步执行异步操作,但我认为如果您开始使用 Promises 来管理问题的异步性质,这很容易解决。
  • 您能否更具体地说明您要做什么以及遇到了什么问题?
  • 我已经更新了帖子
  • 没有进入关于你应该做什么的持续讨论,我想说你真的应该一次性将所有图像 ID 发送到你的后端脚本,一次 go 更新(对它们做任何事情),然后发回响应。遍历循环并为每个循环创建一个新的$.ajax() 请求是多余的。对数组运行for() 循环,收集适当的ID,将它们发送到后端进行(批处理)处理。然后您可以返回更新的信息,这些信息可以添加到您的数组中。这样您就可以使用单个 $.ajax() 实例。

标签: javascript arrays ajax for-loop


【解决方案1】:

发布问题更新:我在您粘贴所有代码之前写了这个。它仍然适用,但还有一些想法:

  • 您似乎只是将数据转储到 SQL 查询字符串中。 Little Bobby Tables 会很自豪,但您应该担心 SQL 注入。
  • 如果您坚持自己编写 std new XMLHttpRequest(); 代码(而不是使用库,如 fetch 或 jquery),则应将其包装在函数中(url、data、method、successCb、errorCb)。图书馆会有所帮助。
  • 在您标记的错误代码中,真正让您感到困扰的是:

i 早已移动,与用于调用的索引不匹配。

loadedImageId[i] = grabPic.responseText;

继续,原来的aysnc解释:

异步代码

您正在讨论如何处理一般异步任务,包括 ajax 调用。

有很多方法可以解决这个问题,特别是callbackspromises

虽然您可以以同步方式执行此操作,但对于玩具或快速破解以外的任何事情,最好使用异步数据。

示例

首先,定义我们的服务。在这种情况下,它不会离开我们的机器,但原理是一样的。您发送一些东西(个人资料 ID)并取回一些东西(个人资料图片网址)。

// After ~1-2 seconds, answer the callback with the evenness of the input
var isEvenAjax = function(num,cb) {
  setTimeout(function(){
    var isEven = num % 2 === 0;
    cb(num + " is " + (isEven ? "Even" : "Odd"));
  },(Math.floor(Math.random() * 12) + 3) * 150);
};

你可以有不同的签名,但这是症结所在。您将数据放入某物,稍等片刻,然后得到响应。

例如:

isEvenAjax(2,console.log);
isEvenAjax(3,console.log);
isEvenAjax(7,console.log);

可能会产生以下反馈:

"7 is Odd"
"2 is Even"
"3 is Odd"

还有我们的测试数据:

var information = [
  10,11,12,
];

现在将我们的数据发送到服务并取回一些东西。一个简单的 foreach 可以处理这个问题(注意:这是为了简单的演示目的。这可能会很快变得非常混乱。Promise 是一个很好的方法)。

var getInformationResponses = function(information,cb) {
  var responses = [];
  information.forEach(function(i){
    isEvenAjax(i,function(response){
      console.log("Feedback for " + i + " is: " + response);
      responses.push({num:i,response:response});
      if (responses.length >= information.length){
        cb(responses);
      }
    });
  });
};

请注意,包装所有异步调用的函数本身是异步的(并且,在我们的回调样式下,它需要一个“完成”回调)。

分解:

声明一个响应数组(我们将所有结果放入其中)后,循环遍历所有信息元素:

var responses = [];
information.forEach(function(i){

对于每个元素,进行异步调用。

isEvenAjax(i,function(response){

对于每个元素的回调(例如,从长时间运行的服务返回数据时),用 console.log 记录(用于演示)并将结果原始数据推送到响应数组。维护源数据对于所有应用程序可能并不重要,但在某些情况下(例如哪些配置文件 ID 对应于哪些配置文件 url)它会。回想一下:异步调用永远不会保证顺序。

console.log("Feedback for " + i + " is: " + response);
responses.push({num:i,response:response});

现在,检查响应数量是否与请求匹配。如果不是,那么不是所有的结果都在并且什么都不做。如果是,则触发主回调并将完整数据发送回主调用者。

if (responses.length >= information.length){
  cb(responses);
}

所以举个例子:

getInformationResponses(information,console.log);

可以返回如下内容:

"Feedback for 10 is: 10 is Even"
"Feedback for 12 is: 12 is Even"
"Feedback for 11 is: 11 is Odd"
[[object Object] {
  num: 10,
  response: "10 is Even"
}, [object Object] {
  num: 12,
  response: "12 is Even"
}, [object Object] {
  num: 11,
  response: "11 is Odd"
}]

承诺

这个练习纯粹是为了探索如何处理异步调用,并且在生产环境中表现不佳。错误处理等问题(ajax 调用失败)在这里没有解决。

正如 CallMeNorm 所述,promises 可能很棒。我现在没有时间介绍它们。

【讨论】:

  • 感谢您的帮助,我将不得不研究 Promise 并检查一下。
【解决方案2】:

就目前而言,您的示例将引发一些错误

information[i] 没有doAjaxstuff 方法。但是,我认为您正在尝试使用现代浏览器中本机的 Promises 可以轻松完成,甚至 jquery 3.0 也具有兼容的实现。在这种情况下,您可以执行以下操作:

var promises = information.map(function(piece, index) {
    //doAjaxstuff must should return a promise 
    return Promise.resolve([index, doAjaxstuff(piece)]);
});

var inOrderPromises = promises.reduce(function(state, value) {
        return state[value[0], value[1]];
    }, []);
});

Promises.all(inOrderPromises)
.then(function(inOrderValues) {
   //doYourThing
});

【讨论】:

  • 我猜它是 pseudo 代码,并且 OP 知道 doAjaxstuff() 不是有效方法。
  • 是的,很抱歉我使用doAjaxStuff() 来举例。请看我的更新
【解决方案3】:

Ajax 调用是异步的,这意味着它们不会等待 for 循环完成。如果您想“暂停”迭代并仅在 ajax 调用返回时恢复,则必须将其设置为同步。

你可以通过添加async: false来做到这一点

更多信息请查看jquery docs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-19
    • 2018-05-01
    • 2023-03-19
    • 2012-07-21
    • 1970-01-01
    • 2021-11-20
    • 2022-01-23
    相关资源
    最近更新 更多