只有当异步获取请求完成时,才能继续循环

Only continue for loop when async get request finishes

本文关键字:继续 循环 完成时 请求 异步 获取      更新时间:2023-09-26

我正在编写一个工具,该工具将循环遍历id的列表(由id_list中的id表示)。我们检查一个缓存对象,看看我们是否已经有了id的值。如果我们还没有给定id的值,我们需要发出get请求来获取相关值,然后将其添加到缓存中。

在执行一个async获取请求所花费的时间内,整个循环都将运行。这意味着缓存从未实际使用过。在继续循环之前,我是否可以要求get请求完成?通常,我会通过前面的onSuccess函数来链接请求,但由于有更改,因此不会发出请求。

cache = {};
var rating;
for (id in id_list){
   if (id in cache){
       rating = cache[id];
   }else{
       rating = $.get(~~~async get request happens here~~~);
       cache[id] = rating;
   }
   $(".result").append(rating);//display result in ui
}

如果希望for循环在每次迭代之间等待,则不能使用它。一种常见的设计模式是为给定的迭代创建一个本地函数,然后在每次异步操作完成时调用它。

假设id_list是一个具有属性的对象,您可以这样做:

var cache = {};
var ids = Object.keys(id_list);
var cntr = 0;
function next() {
    var id;
    if (cntr < ids.length) {
        id = ids[cntr++];
        // see if we can just get the value from the cache
        if (id in cache) {
            $(".result").append(cache[id]);
            // schedule next iteration of the loop
            setTimeout(next, 1);
        } else {
            // otherwise get rating via Ajax call
            $.get(...).then(function(rating) {
                $(".result").append(rating);
                // put rating in the cache
                cache[id] = rating;
                next();
            });
        }
    }
}
next();

或者,如果id_list是一个id数组,您可以将其更改为:

var cache = {};
var cntr = 0;
var id_list = [...];
function next() {
    var id;
    if (cntr < id_list.length) {
        id = id_list[cntr++];
        // see if we can just get the value from the cache
        if (id in cache) {
            $(".result").append(cache[id]);
            // schedule next iteration of the loop
            setTimeout(next, 1);
        } else {
            // otherwise get rating via Ajax call
            $.get(...).then(function(rating) {
                $(".result").append(rating);
                // put rating in the cache
                cache[id] = rating;
                next();
            });
        }
    }
}
next();