javascript 带有 jQ​​uery 异步 AJAX 调用的 while 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19332049/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 15:11:52  来源:igfitidea点击:

While loop with jQuery async AJAX calls

javascriptjqueryajaxdomappend

提问by Aleksandr Shumilov

The thing: I have a page, which has to display undetermined number of images, loaded through AJAX (using base64 encoding on the server-side) one by one.

事情:我有一个页面,它必须显示未确定数量的图像,通过 AJAX(在服务器端使用 base64 编码)逐个加载。

var position = 'front';
while(GLOB_PROCEED_FETCH)
{
    getImageRequest(position);
}

function getImageRequest(position)
{
    GLOB_IMG_CURR++;
$.ajax({
        url: urlAJAX + 'scan=' + position,
        method: 'GET',
        async: false,
        success: function(data) {
            if ((data.status == 'empty') || (GLOB_IMG_CURR > GLOB_IMG_MAX))
            {
                GLOB_PROCEED_FETCH = false;
                return true;
            }
            else if (data.status == 'success')
            {
                renderImageData(data);
            }
        }
    });
}

The problem is that images (constructed with the renderImageData() function) are appended (all together) to the certain DIV only when all images are fetched. I mean, there is no any DOM manipulation possible until the loop is over.

问题是图像(由 renderImageData() 函数构建)仅在获取所有图像时才会(全部一起)附加到特定 DIV。我的意思是,在循环结束之前,不可能进行任何 DOM 操作。

I need to load and display images one by one because of possible huge number of images, so I can't stack them until they all will be fetched.

由于可能有大量图像,我需要一张一张地加载和显示图像,因此在获取所有图像之前我无法堆叠它们。

回答by jfriend00

Your best bet would be to restructure your code to use async ajax calls and launch the next call when the first one completes and so on. This will allow the page to redisplay between image fetches.

最好的办法是重构代码以使用异步 ajax 调用,并在第一个调用完成时启动下一个调用,依此类推。这将允许页面在图像提取之间重新显示。

This will also give the browser a chance to breathe and take care of its other housekeeping and not think that maybe it's locked up or hung.

这也将使浏览器有机会喘口气并处理其其他内务,而不是认为它可能被锁定或挂起。

And, use async: 'false'is a bad idea. I see no reason why properly structured code couldn't use asynchronous ajax calls here and not hang the browser while you're fetching this data.

而且,使用async: 'false'是个坏主意。我看不出为什么结构正确的代码不能在此处使用异步 ajax 调用,并且在您获取此数据时不能挂起浏览器。

You could do it with asynchronous ajax like this:

你可以像这样使用异步 ajax 来做到这一点:

function getAllImages(position, maxImages) {
    var imgCount = 0;

    function getNextImage() {
        $.ajax({
            url: urlAJAX + 'scan=' + position,
            method: 'GET',
            async: true,
            success: function(data) {
                if (data.status == "success" && imgCount <= maxImages) {
                    ++imgCount;
                    renderImageData(data);
                    getNextImage();
                }
            }
        });
    }
    getNextImage();
}

// no while loop is needed
// just call getAllImages() and pass it the 
// position and the maxImages you want to retrieve
getAllImages('front', 20);

Also, while this may look like recursion, it isn't really recursion because of the async nature of the ajax call. getNextImage()has actually completed before the next one is called so it isn't technically recursion.

此外,虽然这可能看起来像递归,但由于 ajax 调用的异步性质,它并不是真正的递归。 getNextImage()实际上在调用下一个之前已完成,因此从技术上讲它不是递归。

回答by Chris Caviness

Wrong and wrong. Don't user timers, don't chain them. Look at jQuery Deferred / when, it has everything you need.

错与错。不要使用计时器,不要链接它们。看看 jQuery Deferred / when,它有你需要的一切。

var imgara = [];
for (image in imglist) {
  imgara[] = ajax call
}
$.when.apply($, imgara).done(function() {
  // do something
}).fail(function() {
  // do something else
});

回答by Optimus Prime

Try using setInterval()function instead of while().

尝试使用setInterval()function 而不是while().

var fetch = setInterval(loadImage, 2000);

function loadImage(){
    position= new position; //Change variable position here.
    getImageRequest(position);
    if(!GLOB_PROCEED_FETCH){
          clearInterval(fetch);
    }
}