如何在递归的AJAX调用中提供“解决”,以便我可以使用“完成”?

问题描述 投票:1回答:2

我正在做一些重复的AJAX调用,我将数组从前端传递到后端,每当它返回到前端时,数组变小(减1)并最终变为空,因此我的递归调用将停止。

这是我的电话:

function download_required_files(demo_data) {
    var ajaxsecurity = setup_page_params.ajax_nonce;

    jQuery.ajax({
        url: ajaxurl,
        type: 'POST',
        dataType: 'json',
        data: {
            action: 'download_import_files_request',
            security: ajaxsecurity,
            content_install_request_data: JSON.stringify(demo_data),
        },

        success: function (response) {
            console.log(response);
            var data = response.data || false;
            /**
             * If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
             */
            if(!data.remaining_steps || !data.remaining_steps.length) {
                return false;
            }

            if(data.can_continue !== 'yes') {
                return false;
            }

            if(data.remaining_steps && data.remaining_steps.length) {
                demo_data.steps_to_take = data.remaining_steps;
                download_required_files(demo_data);

            }

            $('.demo-loader-content').fadeOut();
        },

        error: function (response) {
            $('.demo-loader-content').fadeOut();

        }
    });
}

假设我有2个步骤来下载文件,这个download_required_files将运行两次,然后它将完成,但如果我这样做:

var download_process = download_required_files(demo_data) //Runs 2 times
download_process.done(function() {  //Do stuff here once that function ran 2 times });

它给了我:Cannot read property 'done' of undefined错误和有充分理由。 download_process不是承诺对象,因为它拥有该属性,它只是......空洞的。

我应该在哪里干预我的download_required_files,以便它向外部代码发出信号“嘿,在承诺的环境中,我已经完成了!”?

javascript promise
2个回答
0
投票

虽然调用$.ajax的结果是一个jqXHR对象,这是有希望的,对于你所描述的我认为我会使用你自己的原生Promise(如果你愿意,还是Deferred)代表整个递归过程:

function download_required_files(demo_data) {
    return new Promise(function(resolve, reject) {
        function worker() {
            var ajaxsecurity = setup_page_params.ajax_nonce;

            jQuery.ajax({
                url: ajaxurl,
                type: 'POST',
                dataType: 'json',
                data: {
                    action: 'download_import_files_request',
                    security: ajaxsecurity,
                    content_install_request_data: JSON.stringify(demo_data),
                },

                success: function (response) {
                    console.log(response);
                    var data = response.data || false;
                    /**
                     * If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
                     */
                    if(!data.remaining_steps || !data.remaining_steps.length) {
                        // *** All done
                        $('.demo-loader-content').fadeOut();
                        resolve();
                    } else if(data.can_continue !== 'yes') {
                        // *** All done; but is this an error condition? If so
                        // use `reject` instead of `resolve` below.
                        $('.demo-loader-content').fadeOut();
                        resolve();
                    } else {
                        demo_data.steps_to_take = data.remaining_steps;
                        worker();  // This is the internal recursive call
                    }
                },

                error: function (response) {
                    $('.demo-loader-content').fadeOut();

                }
            });
        }
        worker();
    });
}

或者使用Deferred代替:

function download_required_files(demo_data) {
    var d = $.Deferred();

    function worker() {
        var ajaxsecurity = setup_page_params.ajax_nonce;

        jQuery.ajax({
            url: ajaxurl,
            type: 'POST',
            dataType: 'json',
            data: {
                action: 'download_import_files_request',
                security: ajaxsecurity,
                content_install_request_data: JSON.stringify(demo_data),
            },

            success: function (response) {
                console.log(response);
                var data = response.data || false;
                /**
                 * If no steps are left, meaning that all required files have been downloaded, proceed with the whole install process.
                 */
                if(!data.remaining_steps || !data.remaining_steps.length) {
                    // *** All done
                    $('.demo-loader-content').fadeOut();
                    d.resolve();
                } else if(data.can_continue !== 'yes') {
                    // *** All done; but is this an error condition? If so
                    // use `d.reject` instead of `d.resolve` below.
                    $('.demo-loader-content').fadeOut();
                    d.resolve();
                } else {
                    demo_data.steps_to_take = data.remaining_steps;
                    worker();  // This is the internal recursive call
                }
            },

            error: function (response) {
                $('.demo-loader-content').fadeOut();

            }
        });
    }
    worker();
    return d.promise();
}

0
投票

这将是我的方法,将单个AJAX请求与内容循环分开,以及DOM更新:

function download_one_file(demo_data) {
    return jQuery.ajax({
        url: ajaxurl,
        type: 'POST',
        dataType: 'json',
        data: {
            action: 'download_import_files_request',
            security: setup_page_params.ajax_nonce,
            content_install_request_data: JSON.stringify(demo_data),
        }
    });
}

function download_loop(demo_data) {
    return download_one_file(demo_data).then(function(data) {
        if (!data) {
            return Promise.reject();
        } else if (data.remaining_steps && data.remaining_steps.length) {
            demo_data.steps_to_take = data.remaining_steps;
            return download_loop(demo_data);
        } else {
            return Promise.resolve();
        }
    });
}

function download_required_files(demo_data) {
    return download_loop(demo_data).finally(function() {
        $('.demo-loader-content').fadeOut();
    });
}
© www.soinside.com 2019 - 2024. All rights reserved.