2016-02-24 3 views
0

У меня есть сложная рекурсивная функция javascript, которая работала очень хорошо, пока мне не понадобилось использовать асинхронные функции (в этом случае jQuery.ajax). Я включил некоторый код под псевдонимом ниже, который дает суть ситуации. Я хотел бы реализовать этот код, используя обещания (вместо текущих обратных вызовов), но не могу решить, как справиться с рекурсией и несколькими условными вызовами ajax. Если я правильно понимаю обещания, они позволят вам действовать по возврату асинхронного вызова, но как мне разобраться с ситуацией ниже?Множественные условные асинхронные рекурсивные функции и обещания jQuery

function wrapperFunction(success,error) { 
    var level = 0; 
    result = []; 

    var innerFunction = function(info,result,success,error) { 
     level++; 

     jQuery.ajax({ 
      url: 'baseurl1' + info, 
      success: parseData, 
      error: error 
     }); 

     function parseData(data) { 
      data.forEach(function(item) { 
       result.push(item.something); 

       if (item.info) { 
        innerFunction(item.info, result, success, error); 
       } 
      }); 

      if (data.condition) { 
       jQuery.ajax({ 
        url: 'baseurl2' + info, 
        success: parseData2, 
        error: error 
       }); 
      } 

      function parseData2(data2) { 
       data2.forEach(function(item2) { 
        if (item2.condition) { 
         jQuery.ajax({ 
          url: 'baseurl3' + info, 
          success: parseData3, 
          error: error 
         }); 
        } 
       }); 
       function parseData3(data3) { 
        if (data3.condition) { 
         jQuery.ajax({ 
          url: 'baseurl4' + info, 
          success: parseData4, 
          error: error 
         }); 
        } 
        function parseData4(data) { 
         result.push(data2.something + data4.something); 
        } 
       } 
      } 

      level--; 
      if (level == 0 && success) { 
       success(result); 
      } 
     } 

    } 

    innerFunction('rootinfo', result, success, error); 
} 

wrapperFunction(
    function(data) { 
     // process success 
    }, 
    function(err) { 
     // handle errors 
    } 
} 

Как я уже сказал, это только псевдокод. Сначала я извлек его из своего реального кода, чтобы узнать, могу ли я окунуться в фактическую структуру. Я знаю, что это работает, если ajax вызывает синхронный вызов, но теперь они асинхронны, он только иногда работает (в зависимости от того, как быстро возвращаются вызовы).

Как реализовать эту ситуацию, используя обещания?

EDIT

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

+0

Почему вы хотите использовать обещания? Они не дают никакой реальной выгоды от того, что у вас есть. Также обратите внимание, что здесь нет рекурсии. Вероятно, вы могли бы убрать код, чтобы сделать его более элегантным, но это будет зависеть от объема, необходимого для каждой функции и данных, которые она извлекает. –

+0

InnerFunction вызывает ajax-запрос, который вызывает parseData при успешном выполнении, который вызывает определенные вызовы функции innerFunction. Это похоже на рекурсию. –

+0

Вы можете сделать что-то вроде этого: https://jsfiddle.net/sandenay/0pa0L9dx/ –

ответ

0

У меня есть работа с помощью Sandeep Nayak (см. Комментарии выше). Мне показалось, что я публикую рабочую версию псевдокода для всех, кто попадает на этот пост с аналогичной проблемой.

Я по существу добавил два уровня обещаний (внешний и внутренний), где наружное обещание разрешается, если все внутренние обещания разрешены. Вероятно, существует возможность для убирания кода, но он работает так, как он есть.

function wrapperFunction(success,error) { 
    var level = 0; 
    var result = []; 
    var outerPromises = []; 

    var innerFunction = function(info,result,success,error) { 
     var outerPromise = new jQuery.Deferred(); 
     outerPromises.push(outerPromise); 

     level++; 

     jQuery.ajax({ 
      url: 'baseurl1' + info, 
      success: parseData, 
      error: error 
     }); 

     function parseData(data) { 
      data.forEach(function(item) { 
       result.push(item.something); 

       if (item.info) { 
        innerFunction(item.info, result, success, error); 
       } 
      }); 

      if (data.condition) { 
       jQuery.ajax({ 
        url: 'baseurl2' + info, 
        success: parseData2, 
        error: error 
       }); 
      } else { 
       outerPromise.resolve(); 
      } 

      function parseData2(data2) { 
       var innerPromises = []; 

       data2.forEach(function(item2) { 
        var innerPromise = new jQuery.Deferred(); 
        innerPromises.push(innerPromise); 

        if (item2.condition) { 
         jQuery.ajax({ 
          url: 'baseurl3' + info, 
          success: parseData3, 
          error: error 
         }); 
        } else { 
         innerPromise.resolve(); 
        } 

        function parseData3(data3) { 
         if (data3.condition) { 
          jQuery.ajax({ 
           url: 'baseurl4' + info, 
           success: parseData4, 
           error: error 
          }); 
         } else { 
          innerPromise.resolve(); 
         } 
         function parseData4(data) { 
          result.push(data2.something + data4.something); 

          innerPromise.resolve(); 
         } 
        } 
       }); 

       jQuery.when.apply(undefined, innerPromises).then(function() { outerPromise.resolve(); }); 
      } 

      level--; 
      if (level == 0 && success) { 
       jQuery.when.apply(undefined, outerPromises).then(function() { success(result); }); 
      } 
     } 

    } 

    innerFunction('rootinfo', result, success, error); 
} 

wrapperFunction(
    function(data) { 
     // process success 
    }, 
    function(err) { 
     // handle errors 
    } 
} 
Смежные вопросы