Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Рекурсия промисов. Все правильно? (https://javascript.ru/forum/misc/69674-rekursiya-promisov-vse-pravilno.html)

Alexandroppolus 13.07.2017 11:42

Цитата:

Сообщение от nerv_
Прозвучит странно, но я бы не называл это рекурсией. Скорее просто отложенный вызов функции самой себя (привет асинхронность).

У рекурсии есть прямой и обратный ход, глубина.

я думаю, тут некая разновидность хвостовой рекурсии )

SergeyERjs 13.07.2017 13:02

Функция вызывает саму себя, значит это рекурсия.
Стек вызовов из-за асинхронности не растет.
Назовите это - асинхронная рекурсия. :)

SergeyERjs 13.07.2017 13:10

Меня другое волнует.
Синхронный код был простой и понятный.
Я хочу:
1. Убедиться, что эквивалентный асинхронный код правильный.
По тестам это так, но вдруг я что-то не учел.
2. Чтобы асинхронный код был понятен.
Не верю, что я решаю уникальную задачу. Возможно уже есть общепринятые паттерны на этот случай.

SergeyERjs 13.07.2017 13:23

И в последнем варианте мне не нравится один момент.
В теле "цикла" приходится добавлять return в двух местах. Кажется, не очевидно, для чего это делается. Меня, как JSера с 2-хмесячным стажем, еще месяц назад это ввело бы в ступор. :blink:
whilePromise(
	isNeedContinue.bind(null, obj),
	function() {
		*!*return*/!* doAnything()
			.then(function() {
				console.log("Что-то еще в цикле...");
				*!*return*/!* Promise.resolve(obj);
			}, Promise.reject.bind(Promise))
	}
)

Или я зря страдаю?

Alexandroppolus 13.07.2017 14:00

SergeyERjs,
зря страдаешь.

"return в двух местах" - это когда в пределах одной функции. Бытует мнение, что это антипаттерн. Хотя нельзя сказать наверняка. (с)

У тебя ретурны в разных функциях, только не обязательно делать return Promise.resolve(obj);, достаточно просто return obj;

Promise.reject.bind(Promise) вообще ни к селу ни к городу. Как ты это придумал, ума не приложу. Наверняка читал говностатейки по программированию на каком-нибудь говносайтишке.

https://learn.javascript.ru/ - здесь и только здесь надо начинать постигать.

Правильный вариант:
whilePromise(
	isNeedContinue.bind(null, obj),
	function() {
		return doAnything()
			.then(function(data) {
				console.log("Что-то еще в цикле...");
				return data;
			});
	}
)

Тут просто передаем то значение data, которое получили в промисе doAnything(). А вот если надо будет воткнуть что-то асинхронное между итерациями, тогда возвращаем промис.

nerv_ 13.07.2017 14:07

Цитата:

Сообщение от Alexandroppolus
я думаю, тут некая разновидность хвостовой рекурсии )

а как бы вы назвали это:
function foo() {
  setTimeout(foo, 1e3)
}
foo()

? :)

SergeyERjs 13.07.2017 14:18

Цитата:

.then(function(data)
Точно! Вот я же чую, чо-то не так. Проще должно быть.
Alexandroppolus, спасибо! :)

Цитата:

Наверняка читал говностатейки...
А вот это лишнее замечание.

Мои основные источники:
https://learn.javascript.ru/
+ https://javascript.ru/manual
+ https://developer.mozilla.org/
+ http://api.jquery.com/ и т.п.

Alexandroppolus 13.07.2017 15:27

Цитата:

Сообщение от nerv_ (Сообщение 458393)
а как бы вы назвали это:
function foo() {
  setTimeout(foo, 1e3)
}
foo()

? :)

ну по сути это в кратком виде тема сабжа.

И да, это похоже на хвостовую рекурсию (после того, как компилятор её оптимизирует, конечно). Только там итерации следуют непрерывно друг за другом, а здесь раскиданы по таскам в event loop. В обоих случаях не нагромождается стек, нет обратного хода.


Часовой пояс GMT +3, время: 21:01.