如何为一组对象运行ajax?

时间:2016-06-14 22:50:29

标签: javascript arrays ajax for-loop

我不确定这是否是使用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不是零(意味着他们已经为他们的个人资料设置了图片 - 否则他们没有&#39; t并且id为0)那么它将使用ajax连接到图像数据库,获取相对于特定ID的图像,然后返回图像源以及更新数组。对不起,我之前没有更具体的说这个,我只是觉得我可以使用更简化的版本。

3 个答案:

答案 0 :(得分:1)

正如你所说的那样,你会抛出一些错误

information[i]没有doAjaxstuff方法。但是,我认为你正在尝试的东西很容易用现代浏览器中的原生Promise来完成,甚至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
});

答案 1 :(得分: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可以处理这个问题(注意:这只是为了简单的演示目的。这可能真的很快就会变得非常混乱。承诺是一个很好的方法)。

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);
      }
    });
  });
};

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

打破这个局面:

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

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可能很棒。我现在没有时间报道他们。

答案 2 :(得分:-1)

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

您可以通过添加async: false

来实现

了解更多信息,请查看jquery docs