2015-04-02 3 views
1

Я изо всех сил пытался заставить это работать, используя объект $.Deferred. Вот очерченная настройка.Дождитесь возвращения ajax во время цикла jquery

g_plans = []; 

$(function(){ 
    // I have to use a custom ajax function, but it returns a promise obj 
    var pageLoadPromise.ajax{(
     url: //call to webmethod 
    }); 

    pageLoadPromise.done(matrix.buildGrid); 

    ... 
}); 

(function(matrix,$,undefined){ 

    var matrix.buildGrid = function(components){ 
     var gridData = data.d.components; 
     buildHeader(gridData); 
     buildRows(gridData); 
    }; 

    function buildHeader(components){ 
      $.each(components,function(key,component){ 
       //does some stuff 
       if(this === that){ 
        //do some other stuff 
       } 
       else{ 
        getPlans(copmonent.COMPONENT_ID); 
        //does other stuff 
       } 
      }); 
     } 
    } 

    function buildRows(components){ 
     //does stuff, but uses data from getPlans 
    } 

    function getPlans(component){ 
     var planPromise = ajax({ 
      url: //call to webmethod 
      data:{ componentId:component} 
     planPromise.done(function(data){ 
      g_plans.push({componentId:componentId,plans:data.d.plans}); 
     }); 
    } 
})(window.matrix = window.matrix || {}, jQuery); 

Проблема заключается в том buildRows начинается до того, как getPlans успевает закончить это Ajax вызов, который вызывает мой вопрос. Я пробовал несколько вещей без успеха. Любая помощь будет оценена по достоинству.

ответ

2

Это самое простое решение, я могу видеть:

1) Есть getPlans() вернуть planPromise обещание, которое затем может быть обработан обратно в функции buildHeader().

function getPlans(component) { 
    var planPromise = ajax({ 
     url: //call to webmethod 
     data:{ componentId:component} 
    }); 
    planPromise.done(function(data) { 
     g_plans.push({componentId: data.componentId, plans: data.d.plans}); 
    }); 
    return planPromise; // return the promise! 
} 

2) Вызов buildRows() из функции buildHeader() вместо matrix.buildgrid используя обещание вернулся из getPlans().

function buildHeader(components) { 
    var lastPromise; 
    $.each(components, function (key, component) { 
     lastPromise = getPlans(component.COMPONENT_ID); 
    }); 
    lastPromise.done(function() { 
     buildRows(components); 
    }); 
} 

Вот JSFiddle, иллюстрирующий основную идею.

Второй шаг не нужен, мне просто стало легче. Другим вариантом было бы вернуть lastPromise от buildHeader() и вернуть его обратно в matrix.buildgrid.

var matrix.buildgrid = function(components) { 
    var gridData = components; 
    var lastPromise = buildHeader(gridData); 
    lastPromise.done(function() { 
     buildRows(components); 
    }); 
}; 

function buildHeader(components) { 
    var lastPromise; 
    $.each(components, function (key, component) { 
     lastPromise = getPlans(component.COMPONENT_ID); 
    }); 
    return lastPromise; 
} 

EDIT:

Чтобы обработать случай lastPromise никогда не получать набор как обещание, вы должны сделать что-то вроде этого:

if (lastPromise && typeof lastPromise === 'object') { 
    lastPromise.done(function() { 
     buildRows(components); 
    }); 
} else { 
    buildRows(components); // or whatever needs to happen here. 
} 

Вот JSFiddle в том числе, что бит в функция buildHeader.

+0

Я добавил 'if-else' в функцию' buildHeader', которую я забыл добавить, и поместил 'lastPromise.done (...)' вне цикла. если 'else' никогда не попадает, а' lastPromise' никогда не устанавливает get, будет ли 'lastPromise' разрешаться? Он работает в моем приложении, но мне интересно, не приведет ли это к нежелательному поведению. –

+0

@RobM 'lastPromise' не может решить, он никогда не будет установлен как обещание. Вам нужно будет сделать еще один оператор 'if-else', чтобы проверить, установлен ли' lastPromise'. Я добавлю ссылку на свой пост с примером. – bowheart

Смежные вопросы