2016-04-01 5 views
0

Как написать свой рекурсивный цикл для правильного выполнения обещаний в порядке? Я пробовал с Promise.all (Array.map (function() {})); что не соответствует моим потребностям, поскольку эти шаги необходимо запускать в последовательности. Я пробовал с обычным обещанием, потому что нашел here, но у него также есть проблемы.Рекурсия и цепочка обещаний Javascript

Обещание для:

var promiseFor = (function(condition, action, value) { 
    var promise = new Promise(function(resolve, reject) { 
     if(!condition(value)) { 
      return; 
     } 
     return action(value).then(promiseFor.bind(null, condition, action)); 
    }); 
    return promise; 
}); 

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

Например: в PHP код, как это:

function loopThrough($source) { 
    foreach($source as $value) { 
     if($value == "single") { 
      //do action 
     } else if($value == "array") { 
      loopThrough($value); 
     } 
    } 
} 

Если я прохожу позволяет сказать, структуру папок и «единый» означает файл, он будет печатать все файлы. Но обещание, что я использую остановки в первом тупике.

РЕДАКТИРОВАТЬ: Добавлена ​​синяя птица, чтобы увидеть, может ли она что-нибудь помочь, все равно то же самое. Вот текущий код петли

var runSequence = (function(sequence, params) { 
    return Promise.each(sequence, function(action) { 
     console.log(action['Rusiavimas'] + ' - ' + action['Veiksmas']); 
     if(params.ButtonIndex && params.ButtonIndex != action['ButtonIndex']) { 
      return Promise.resolve(); 
     } 

     if(action['Veiksmas'].charAt(0) == '@') { 
      var act = action['Veiksmas']; 
      var actName = act.substr(0, act.indexOf(':')).trim(); 
      var actArg = act.substr(act.indexOf(':')+1).trim(); 

      /* This one is the code that figures out what to do and 
       also calls this function to execute a sub-sequence. */ 
      return executeAction(actName, actArg, params); 
     } else { 
      sendRequest('runQuery', action['Veiksmas']); 
     } 
    }); 
}); 

У меня есть 3 последовательности, каждый из которых состоит из 5 действий. Первая и вторая последовательности имеют следующую последовательность, так как это третье действие. Вот результат я получаю (цифры означают какая последовательность):

1 - @PirmasVeiksmas 
1 - @AntrasVeiksmas 
1 - @Veiksmas: list_two 
2 - @PirmasVeiksmas 
2 - @AntrasVeiksmas 
2 - @Veiksmas: list_three 
3 - @PirmasVeiksmas 
3 - @AntrasVeiksmas 
3 - @TreciasVeiksmas 
3 - @KetvirtasVeiksmas 
3 - @PenktasVeiksmas 

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

EDIT2: Codepen пример того, что я сейчас и с визуальным представлением о том, что происходит: Codepen link

Вывод должен быть:

fa1 
second 
sa1 
third 
ta1 
ta2 
ta3 
sa3 
fa3 
+0

является то, что php-код асинхронный? – dandavis

+0

@ dandavis нет, это был просто пример, я просто не могу понять, почему цепочка обещаний прекращается, когда она попадает в первый тупик и должна вернуться назад (рекурсия), чтобы продолжить предыдущий. – IntoDEV

+0

Пожалуйста, всегда цитируйте, где вы нашли код - приписываете автора, и поместите туда ссылку! Btw, [здесь оригинал] (http://stackoverflow.com/a/24660323/1048572) (который также не имеет ошибки) – Bergi

ответ

0

Так что это устраняет проблемы с вашим codepen кодом, так что дает вы хотите.

var sequences = { 
    first: ['fa1', 'second', 'fa3'], 
    second: ['sa1', 'third', 'sa3'], 
    third: ['ta1', 'ta2', 'ta3'] 
}; 

var loopThrough = (function(sequence) { 
    return sequence.forEach(function(action) { 
    return doAction(action); 
    }); 
}); 

var doAction = (function(action) { 
    var promise = new Promise(function(resolve, reject) { 
    console.log(action); 
    if(action == 'second' || action == 'third') { 
     //recurse into sub-sequence 
     return loopThrough(sequences[action]); 
    } else { 
     //do something here 
    } 
    resolve(); 
    }); 
    return promise; 
}); 

loopThrough(sequences.first); 
1

Запуск кучу действий в последовательности может быть сделано с .reduce() вместо .map().

Вот пример:

// Helper function that creates a Promise that resolves after a second 
 
const delay = (value) => new Promise(resolve => setTimeout(() => resolve(value), 1000)); 
 

 
const arr = [1, 2, 3, 4, 5]; 
 

 
// concurrent resolution with `.map()` and `Promise.all()` 
 
Promise.all(arr.map(delay)) 
 
    .then(console.log.bind(console)); // [1, 2, 3, 4, 5] after a second. 
 

 
// sequential resolution with `.reduce()` 
 

 
arr.reduce((promise, current) => 
 
      promise 
 
       .then(() => delay(current)) 
 
       .then(console.log.bind(console)), 
 
      Promise.resolve()); 
 
// second wait, 1, second wait, 2...

Если я правильно понял ваши требования, вы точно не нужно Promise рекурсию, это именно так, как вы нашли для запуска Обещания последовательно. .reduce() может помочь вам с этим проще.

процесс Уменьшение превращает [1,2,3,4,5] в:

Promise.resolve() 
    .then(() => delay(1)) 
    .then(console.log.bind(console)) 
    .then(() => delay(2)) 
    .then(console.log.bind(console)) 
    .then(() => delay(3)) 
    .then(console.log.bind(console)) 
    .then(() => delay(4)) 
    .then(console.log.bind(console)) 
    .then(() => delay(5)) 
    .then(console.log.bind(console)) 

Обратите внимание, что если вы хотите получить доступ ко всем результатам, что вам нужно сделать немного больше работы.Но я оставлю это как упражнение для читателя :)

+0

Спасибо, но я уже решил эту проблему с другим вопросом stackoverflow, оказалось, что у меня были проблемы с jQuery 2.x, так как я перешел к 3.x, проблема решена сама собой. Я не использовал jQuery в самих обещаниях, чтобы держать их независимыми, но просто благодаря тому, что jQuery в моем коде перепутал пару вещей. Редактировать: Если вам интересно, вот сообщение [ссылка] (http://stackoverflow.com/questions/36426786/why-does-this-ajax-request-with-promises-break-the-code-as-running -это-без) – IntoDEV

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