Показать сообщение отдельно
  #21 (permalink)  
Старый 13.05.2014, 19:16
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сообщение от melky
да, я сейчас хотел написать функцию факториала на co.. в общем, мне нужна подготовка)
Все эти co и Q.async на самом деле ничего сложного не делают, а просто автоматически выстраивают такую штуку:
gen.next().value.then(function (value1) {
    gen.next(value1).value.then(function (value2) {
        gen.next(value2).value.then(function (value3) {
            gen.next(value3)...
        });
    })
});


Вот рабочий пример для понимания:
function asyncGet1(value) {
    return new Promise(function (resolve) {
        setImmediate(resolve, value);
    });
}

function asyncGet2(value) {
    return new Promise(function (resolve) {
        setImmediate(resolve, value + 1);
    });
}

function asyncGet3(value) {
    return new Promise(function (resolve) {
        setImmediate(resolve, value * 2);
    });
}

function * genFunc() {

    var x = yield asyncGet1(1);
    console.log('x = ' + x); // x = 1

    var y = yield asyncGet2(x);
    console.log('y = ' + y); // y = 2

    var z = yield asyncGet3(y);
    console.log('z = ' + z); // z = 4

}

//вместо co или Q.async:
var gen = genFunc();

gen.next().value.then(function (x) {
    gen.next(x).value.then(function (y) {
        gen.next(y).value.then(function (z) {
            gen.next(z);
        });
    })
});
yield никакой асинхронностью не занимается, он просто останавливает выполнение генератора до следующего вызова next.

Когда пишешь генератор, можно представлять, что co в паре с yield разбивают genFunc на вот такие «подфункции»:
function next1() {
    asyncGet1(1).then(next2);
}

function next2(value) {
    x = value;
    asyncGet2(x).then(next3);
}

function next3(value) {
    y = value;
    asyncGet3(y).then(next4);
}

function next4(value) {
    z = value;
}
Здесь специально расписал через value, чтобы воспринималось, как promise value.



Кстати, в ES7 возможно будет реализация этого паттерна на уровне языка. Будут введены инструкции async (вместо co, Q.async) и await (вместо yield), и генераторы для это не нужны будут:
async function func() {
    var x = await asyncGet1(1);
    var y = await asyncGet2(x);
    var z = await asyncGet3(y);
}

Последний раз редактировалось Octane, 13.05.2014 в 21:10.
Ответить с цитированием