简体   繁体   English

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

[英]JavaScript promises with nested AJAX calls are not working

On my code I hava a function with 3 nested AJAX calls, in order for it to work I had to set Async=false . 在我的代码上,我有一个带有3个嵌套AJAX调用的函数,为了使其正常工作,我必须设置Async=false

As I have read that Async=false is deprecated I replaced the Async=false with promises . 如我Async=false不赞成使用Async=false所以我用promises代替了Async=false

This is my function before I edited it: 这是我编辑之前的功能:

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;

This function worked perfectly, I got the data end everything worked fine. 此功能运行完美,我得到了数据端一切正常的信息。

Then I changed the function to use promises instead of Async=false , this is the edited function, with promises : 然后我将函数更改为使用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;

And the function call: 和函数调用:

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

The new function is not working, I'm getting back from the firstPromise a wrong json with backslashes, and the returned orders object is empty. 新功能无法正常工作,我从firstPromise返回带有反斜杠的错误json,并且返回的orders对象为空。

Any idea what am I doing wrong? 知道我在做什么错吗? I spent so much time on it but couldn't figure it out. 我花了很多时间,但无法弄清楚。

Thanks in advance. 提前致谢。

Nested ajax calls inside a loop is a hell to manage. 循环内嵌套的ajax调用很难管理。 You can do it like this. 您可以这样做。

  • Create a promise to notify the caller when the whole process is finished 创建一个承诺,以在整个过程完成时通知调用方
  • Wait for all the inner ajax calls to resolve 等待所有内部ajax调用解决
  • Resolve you main promise to notify the caller 解决您的主要承诺,通知呼叫者

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

In the example, note that I use $.when.apply() to wait for an array of deferreds. 在示例中,请注意,我使用$.when.apply()来等待一组延迟。

A bug recently introduced in chrome 52 (august 2016) can cause this kind of behavior : answers for nested requested are ignored. chrome 52(2016年8月)最近引入的一个错误可能导致这种现象:嵌套请求的答案将被忽略。 Hoppefully, it will not last long. 希望它不会持续很长时间。

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

Try to add cache: false 尝试添加缓存:false

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM