When using generators to simulate pseudo-synchronous code, you forgot about one very important point. In order for all this to work, you need an external function that will start your generator and link the input and output of the generator.
For example, you can use the co library. The code with its use can be:
let asyncGet = function(data) { return new Promise(function(resolve) { setTimeout(function() { resolve(data); }, 1000); }); }; co(function * () { let w = yield asyncGet('W'); console.log('The first letter is "%s"', w); let t = yield asyncGet('T'); console.log('The second letter is "%s"', t); let f = yield asyncGet('F'); console.log('The third letter is "%s"', f); return '' + w + t + f; }).then(function(word) { console.log('The process is done and the word is "%s"', word); });
And here is the link to JSFiddle.
In the example above, the generator does return Promises; however, without the correct external function , this is not enough for writing pseudo-synchronous code. Moreover, there are implementations of calling functions that work not only with Promises, but also with simple data and even with other generators.
That same magic defiant function is pretty simple:
let execute = function(generator) { // Рекурсивная функция для вызова следующей итерации генератора let run = function(gen, nextVal) { let next = gen.next(nextVal); if (next.done) { // Генератор выполнен. Пора завершать рекурсивный процесс // и отдавать результат вовне. return Promise.resolve(next.value); } // В генераторе еще остались значения. Предполагаем, что генератор всегда // возвращает Promise. Это очень серьезное допущение и сделано только для простоты // примера. Реальные библиотеки (напр. co) позволяют возвращать и другие типы // данных. return next.value // Дожидаемся получения результата и предаем его в следующую итерацию. .then(function(data) { return run(gen, data); }) // В случае ошибки, бросаем в генератор исключение. .catch(function(err) { return gen.throw(err); }); }; // Создаем экземпляр генератора и инициализируем процесс. // Значение, которое предается в генератор при первом вызове gen.next будет // проигнорировано, поэтому можем смело использовать null return run(generator(), null); };
In real libraries, this code is somewhat more complicated, but the principle remains the same.