Ajax承诺错误"无法读取属性'然后'未定义"尽管回复了承诺

时间:2015-05-19 13:12:27

标签: jquery ajax promise

我尝试使用函数初始化带有3个ajax调用的数据,当这个函数完成时,我想对数据做一些事情。在我可以返回一个承诺之前,我必须等待3个ajax调用才能完成。问题是,如果我等待3个ajax调用完成(使用$ .when(ajax1,ajax2,ajax3).done(...)),我得到错误"无法读取属性&#39 ;然后'未定义"

这是我的代码

function myInit() {
    initData().then(function() {
        console.log("a");
    });
}

function initData() {
    var results = {
        categories: [],
        commandes: [],
        users: []
    };
    var ajaxCategories = $.ajax({
        url: url + '/categorie/getAll',
        success: function(data) {
            results.categories = data;
        }
    });

    var ajaxCommandes = $.ajax({
        url: url + '/statistique/getSimpleCommandes',
        success: function(data) {
            results.commandes = data;
        }
    });
    var ajaxUsers = $.ajax({
        url: url + '/statistique/getSimpleUsers',
        success: function(data) {
            results.users = data;
        }
    });
    $.when(ajaxUsers, ajaxCommandes, ajaxCategories)
        .done(function() {
            results.commandes.forEach(function(commande) {
                results.users.forEach(function(user) {
                    if (user.id == commande.user)
                        commande.user = user.nom;
                });
            });
            return $.Deferred().resolve();
        });
}

我在$ .when中回复了一个承诺。如果我将此返回移动到when之外,它可以正常工作,但是我冒险退出该函数并继续使用未加载数据的代码。我的错误在哪里?

2 个答案:

答案 0 :(得分:0)

done的回调中返回承诺并不会使initData函数返回任何内容。

$.when调用之外创建承诺,以便您可以在回调中解析它并从initData返回:

var promise = $.Deferred();
$.when(ajaxUsers, ajaxCommandes, ajaxCategories)
    .done(function(){
        results.commandes.forEach(function(commande){
            results.users.forEach(function(user){
                if (user.id == commande.user)
                    commande.user = user.nom;
            });
        });
        promise.resolve();
    });
return promise.promise();

或者,返回done返回的承诺:

return $.when(ajaxUsers, ajaxCommandes, ajaxCategories)
    .done(function(){
        results.commandes.forEach(function(commande){
            results.users.forEach(function(user){
                if (user.id == commande.user)
                    commande.user = user.nom;
            });
        });
    });

使用done方法添加的处理程序按添加顺序调用,因此调用程序添加的任何处理程序都将在处理程序之后运行。

如果您希望在您返回的承诺中传递done处理程序中的数据,请通过resolve来电发送:

var promise = $.Deferred();
$.when(ajaxUsers, ajaxCommandes, ajaxCategories)
    .done(function(){
        results.commandes.forEach(function(commande){
            results.users.forEach(function(user){
                if (user.id == commande.user)
                    commande.user = user.nom;
            });
        });
        promise.resolve(results);
    });
return promise.promise();

答案 1 :(得分:-1)

initData()未返回承诺,因为该函数中没有return语句。您需要返回$.when给您的承诺。

另外,为了链接动作并从回调中返回一些内容,您需要使用.then而不是.done

function initData() {
    var results = {
        categories: [],
        commandes: [],
        users: []
    };
    var ajaxCategories = $.ajax({
        url: url + '/categorie/getAll',
        success: function(data) {
            results.categories = data;
        }
    });

    var ajaxCommandes = $.ajax({
        url: url + '/statistique/getSimpleCommandes',
        success: function(data) {
            results.commandes = data;
        }
    });
    var ajaxUsers = $.ajax({
        url: url + '/statistique/getSimpleUsers',
        success: function(data) {
            results.users = data;
        }
    });
    return $.when(ajaxUsers, ajaxCommandes, ajaxCategories)
//  ^^^^^^
    .then(function() {
//   ^^^^
        results.commandes.forEach(function(commande) {
            results.users.forEach(function(user) {
                if (user.id == commande.user)
                    commande.user = user.nom;
            });
        });
        return results; // I guess that is what you wanted
    });
}

您甚至可以通过不使用全局results变量来进一步提升这一点,但要将其置于回调本地:

function initData() {
    return $.when(
        $.get(url + '/categorie/getAll'), 
        $.get(url + '/statistique/getSimpleCommandes'),
        $.get(url + '/statistique/getSimpleUsers')
    ).then(function(categoriesRes, commandesRes, userRes) {
        var results = {
            categories: categoriesRes[0],
            commandes: commandesRes[0],
            users: userRes[0]
        };
        results.commandes.forEach(function(commande) {
            results.users.forEach(function(user) {
                if (user.id == commande.user)
                    commande.user = user.nom;
            });
        });
        return results;
    });
}