嵌套AJAX调用的JavaScript承诺不起作用

时间:2016-08-12 07:05:26

标签: javascript ajax asynchronous promise

在我的代码中,我有一个带有3个嵌套AJAX调用的函数,为了使它工作,我必须设置Async=false

我已经读过Async=false已被弃用,我将Async=false替换为promises

在编辑之前,这是我的功能:

self.getOrders = function (name) {
    var orders= [];
    var order= function (item, type1, type2) {
        var self = this;
        self.order= item;
        self.type1= type1;
        self.type2= type2;
    }

$.ajax({
    url: "/API/orders/" + name,
    type: "GET",
    async: false,
    success: function (orderResults) {
        var mappedOrders = $.map(orderResults, function (orderItem) {
        $.ajax({
            url: "/API/orders/property/" + orderItem.id + "/type1",
            type: "GET",
            async: false,
            success: function (property1Results) {
                 $.ajax({
                     url: "/API/orders/property/" + orderItem.id + "/type2",
                     type: "GET",
                     async: false,
                     success: function (property2Results) {
                          orders.push(new order(orderItem, property1Results, property2Results));
                        }
                    });
                  }
                });
            })
        }
    });
    return orders;

这个功能完美无缺,我得到的数据一切正常。

然后我将函数更改为使用promises而不是Async=false, 这是已修改的功能,promises

//The begin of the function- same as first one
var orders= [];
var firstPromise = $.ajax({
        url: "/API/orders/" + name,
        type: "GET"
    });
    $.when(firstPromise).done(function (orderResults) {
        var mappedOrders = $.map(orderResults, function (orderItem) {
            var secondPromise = $.ajax({
                url: "/API/orders/property/" + orderItem.id + "/type1",
                type: "GET"
            });
            $.when(secondPromise).done(function (property1Results) {
                var thirdPromise = $.ajax({
                    url: "/API/orders/property/" + orderItem.id + "/type2",
                    type: "GET"
                });
                $.when(thirdPromise).done(function (property2Results) {
                    orders.push(new order(orderItem, property1Results, property2Results));
                });
            });
        });
    });
    return orders;

函数调用:

self.populateOrders = function (name) {
    var mappedOrders = $.map(self.service.getOrders(name), function (item) {
        return new Order(item)
        });
    self.orders(mappedOrders);
}

新功能不起作用,我从firstPromise用反斜杠返回错误的json,返回的orders对象为空。

知道我做错了什么吗?我花了很多时间在上面,但无法弄明白。

提前致谢。

2 个答案:

答案 0 :(得分:0)

循环内嵌套的ajax调用是一个难以管理的地狱。你可以这样做。

  • 创建一个承诺,在整个过程完成时通知调用者
  • 等待所有内部ajax调用解析
  • 解决您通知来电者的主要承诺

self.getOrders = function (name) {
    var mainDeferred = $.Deferred();
    var orders = [];
    var order = function (item, type1, type2) {
        var self = this;
        self.order = item;
        self.type1 = type1;
        self.type2 = type2;
    }

    $.ajax({
        url: "/API/orders/" + name,
        type: "GET",
        success: function (orderResults) {
            var innerwait = [];

            var mappedOrders = $.map(orderResults, function (orderItem) {
                var ajax1 = $.ajax({
                    url: "/API/orders/property/" + orderItem.id + "/type1",
                    type: "GET"
                });
                var ajax2 = $.ajax({
                    url: "/API/orders/property/" + orderItem.id + "/type2",
                    type: "GET"
                });
                $.when(ajax1, ajax2).done(function (property1Results, property2Results) {  
                    orders.push(new order(orderItem, property1Results[0], property2Results[0])))
                });
                innerwait.push(ajax1, ajax2);
            });;

            $.when.apply(null, innerwait) //make sure to wait for all ajax requests to finish
                .done(function () {
                    mainDeferred.resolve(orders); //now that we are sure the orders array is filled, we can resolve mainDeferred with orders array
                });
        }
    });

    return mainDeferred.promise();
}


self.populateOrders = function (name) {
    self.service.getOrders(name).done(function (orders) { //use .done() method to wait for the .getOrders() to resolve
        var mappedOrders = $.map(orders, function (item) {
            return new Order(item)
        });
        self.orders(mappedOrders);
    });
}

在示例中,请注意我使用$.when.apply()等待延迟数组。

答案 1 :(得分:-4)

最近在chrome 52(2016年8月)中引入的一个错误可能会导致这种行为:忽略嵌套请求的答案。 总而言之,它不会持续很长时间。

https://bugs.chromium.org/p/chromium/issues/detail?id=633696

尝试添加缓存:false