使用 promise 的嵌套 ajax 次调用

Nested ajax calls using promise

我需要使用 Promise 重构一个标准的 ajax 金字塔。最初我使用 async:false 的标准 AJAX 调用。这使得页面变慢了。所以我决定用 AJAX Promise.

替换嵌套的 AJAX 调用

这是我原来的 ajax 电话。

$.ajax({
            type:"POST",
            url:'@Url.Action("GetDesks", "OrderForm")',
            data:{ String(agents.val())},
            async:false,
            success:function (desks) {
                if (desks!=undefined || desks!=null || desks!= '') {
                    var deskList=$("#DeskList").data("kendoDropDownList");
                    deskList.dataSource.data(desks);
                    deskList.value("");
                    deskList.trigger('change');
                    var desklist = $.map(desks, function(val,index) {     
                        return val.Value;
                    }).join(",");                   
                    $.ajax({
                        type:"POST",
                        url:'@Url.Action("GetUsers", "OrderForm")',
                        data:{ Desks:desklist },                        
                        async:false,
                        success:function (users) { 
                            if (users!=undefined || users!=null || users!= '') {
                                var usersList=$("#DeskUsers").data("kendoDropDownList");
                                usersList.dataSource.data(users);
                                usersList.select(0);
                                usersList.refresh();
                            }
                        },
                    });
                }
            },

        });

我尝试将上面的修改为:

$.ajax({
            type:"POST",
            url:'@Url.Action("GetDesks", "OrderForm")',
            data:{ String(agents.val())}
        }).done(function (desks) {  
            if (desks!=undefined || desks!=null || desks!= '') {
                var deskList=$("#DeskList").data("kendoDropDownList");
                deskList.dataSource.data(desks);
                deskList.value("");
                deskList.trigger('change');
                var desklist = $.map(desks, function(val,index) {     
                    return val.Value;
                }).join(",");                   
                $.ajax({
                    type:"POST",
                    url:'@Url.Action("GetUsers", "OrderForm")',
                    data:{ Desks:desklist }
                })
                //How to apply promise after this?
        });

我将 promise 应用于拳头 ajax 调用。但是在将相同的方法应用于第二个 ajax 调用时有点混乱。

我如何应用上述案例的承诺?

我从未使用过 ajax 承诺。我只用过as3.

但是,如果您希望他们异步执行,请让您的 GetDesks 保持不变。在第一个 .done 内的成功处理程序之外获取 GetUsers,并在类似于之前的下一行中执行它。

例如

GetUsers.done(函数...);

GetDesks.done(函数...);

首先,不要使用async: false。我也不知道 data: {String(agents.val())} 语法是什么,但您可以将代码改进为:

$.post('@Url.Action("GetDesks", "OrderForm")', { Agents: String(agents.val()) }).then(function(desks) {
    if (desks != undefined || desks != null || desks != '') {

        var deskList = $("#DeskList").data("kendoDropDownList");
        deskList.dataSource.data(desks);
        deskList.value("");
        deskList.trigger('change');

        var desklist = $.map(desks, function(val, index) {
            return val.Value;
        }).join(",");

        return $.post('@Url.Action("GetUsers", "OrderForm")', { Desks: desklist }).then(function() {
            if (users != undefined || users != null || users != '') {
                var usersList = $("#DeskUsers").data("kendoDropDownList");
                usersList.dataSource.data(users);
                usersList.select(0);
                usersList.refresh();
            }
        });
    }
}).then(function() {
    // both operatioins are completed
});

组合handler就是使用Promise接口的then()方法

它接受所有三个处理程序作为参数。关于 jQuery,在 1.8 版本之前,

您可以将函数数组传递给 then() 方法:

像这样

$.ajax({url: "/ServerResource.txt"}).then([successFunction1, successFunction2, successFunction3], 
                                          [errorFunction1, errorFunction2]);

//same as

var jqxhr = $.ajax({
  url: "/ServerResource.txt"
});

jqxhr.done(successFunction1);
jqxhr.done(successFunction2);
jqxhr.done(successFunction3);
jqxhr.fail(errorFunction1);
jqxhr.fail(errorFunction2);

根据一些假设,您似乎想要这样的东西:

$.ajax({
    url: '@Url.Action("GetDesks", "OrderForm")',
    type: 'POST',
    data: { 'Agents': agents.val() } //probably?
}).then(function (desks) {
    if (desks) {
        return $.ajax({
            url: '@Url.Action("GetUsers", "OrderForm")',
            type: 'POST',
            data:{ 'Desks': $.map(desks, function(val) { return val.Value; }).join() }
        }).then(function (users) {
            if (users) {
                // `desks` is still in scope allowing *both* kendoDropDownLists to be updated together
                var usersList = $("#DeskUsers").data("kendoDropDownList");
                usersList.dataSource.data(users);
                usersList.select(0);
                usersList.refresh();
                var deskList = $("#DeskList").data("kendoDropDownList");
                deskList.dataSource.data(desks);
                deskList.value("");
                deskList.trigger('change'); //probably do this last?
            } else {
                return new Error('No users found');
            }
        }, function(jqXHR, textStatus, errorThrown) {
            return new Error(textStatus);
        });
    } else {
        return new Error('No desks found');
    }
}, function(jqXHR, textStatus, errorThrown) {
    return new Error(textStatus);
}).fail(function(error) {
    console.log(error);
});

除了使用 promises 之外,主要的变化是将 $("#DeskList").data("kendoDropDownList")... 移动到第二个 "success handler"。

这将保证两个列表都更新,或都不更新,并提供机会 `.trigger('change') 在两个列表都更新后,这可能很重要。在这方面实际上不需要承诺 - 您可以在原始代码中执行相同的操作(即使使用 async:true)。