Итак, не так давно мне пришлось столкнуться с довольно популярной задачей преобразования асинхронного кода в синхронный в рамках цикла. В моем случае это была работа с AmazonAPI методами productSearch. Все бы ничего, да вот только данный API очень не любит когда к нему обращаются слишком часто, а мне было необходимо в цикле опрашивать состояние продуктов.
В данной статье я на практическом примере расскажу о реализации способа, которым я воспользовался для решения моей задачи. Приступим.
Для реализации нам понадобятся: promises (я буду использовать библиотеку q), версия nodejs с поддержкой генераторов, подопытная асинхронная функция (будем использовать setTimeout).
Результатом выполнения данного скрипта будет:
Как мы видим все наши асинхронные вызовы проходят в синхронном режиме. Для поддержки более старых версий(не поддерживающих генераторы), я добавил функцию “oldIterator”, которая будет работать аналогично генератору.
PS: данный код будет работать аналогично и в JavaScript, достаточно заменить библиотеку “Q” на родные “Promise”.
На этом все, спасибо за внимание!
В данной статье я на практическом примере расскажу о реализации способа, которым я воспользовался для решения моей задачи. Приступим.
Для реализации нам понадобятся: promises (я буду использовать библиотеку q), версия nodejs с поддержкой генераторов, подопытная асинхронная функция (будем использовать setTimeout).
var q = require("q"); function* itemGenerator(data) { var i, len = data.length; for(i = 0; i < len; i++) { yield data[i]; } } function oldIterator(data) { var i = -1, len = data.length; return { "next": function() { i++; return { "done": i == len, "value": data[i] }; } } } function main() { var def = q.defer(), items = [1, 2, 3, 4, 5]; (function foo(gen) { var genItem = gen.next(), item = genItem.value; if(genItem.done) { def.resolve(true); return; } console.log("start call for", item); setTimeout(function() { console.log("end call for", item); foo(gen); }); })(itemGenerator(items)) return def.promise; } main().then(function(flag) { console.log("promise has been resolved", flag); });
Результатом выполнения данного скрипта будет:
> node async_sync.js start call for 1 end call for 1 start call for 2 end call for 2 start call for 3 end call for 3 start call for 4 end call for 4 start call for 5 end call for 5 promise has been resolved true
Как мы видим все наши асинхронные вызовы проходят в синхронном режиме. Для поддержки более старых версий(не поддерживающих генераторы), я добавил функцию “oldIterator”, которая будет работать аналогично генератору.
PS: данный код будет работать аналогично и в JavaScript, достаточно заменить библиотеку “Q” на родные “Promise”.
На этом все, спасибо за внимание!