while循环使用jQuery异步AJAX调用

时间:2022-08-23 18:09:20

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.

我需要逐个加载和显示图像,因为可能有大量的图像,所以我不能将它们堆叠起来,直到它们都被取出。

3 个解决方案

#1


21  

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()实际上已在完成下一个调用之前完成,因此它不是技术上的递归。

#2


-2  

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

#3


-3  

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

尝试使用setInterval()函数而不是while()。

var fetch = setInterval(loadImage, 2000);

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

#1


21  

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()实际上已在完成下一个调用之前完成,因此它不是技术上的递归。

#2


-2  

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

#3


-3  

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

尝试使用setInterval()函数而不是while()。

var fetch = setInterval(loadImage, 2000);

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