Promises и генераторы позволяют вам писать асинхронный код. Я не понимаю, почему оба этих механизма введены в ECMA script 6. Когда лучше всего использовать promises, а когда генераторы?
JavaScript асинхронное программирование: promises против генераторов
Ответ 1
Между этими двумя методами нет никакой оппозиции. Они сосуществуют друг с другом, прекрасно дополняя друг друга. Promises дает вам возможность получить результат асинхронной операции, которая пока недоступна. Он решает проблему Pyramid of Doom. Поэтому вместо:
function ourImportantFunction(callback) {
//... some code 1
task1(function(val1) {
//... some code 2
task2(val1, function(val2) {
//... some code 3
task3(val2, callback);
});
});
}
вы можете написать:
function ourImportantFunction() {
return Promise.resolve()
.then(function() {
//... some code 1
return task1(val3)
})
.then(function(val2) {
//... some code 2
return task2(val2)
})
.then(function(val2) {
//... some code 3
return task3(val2);
});
}
ourImportantFunction().then(callback);
Но даже с Promises вы должны писать код в асинхронном режиме - вы всегда должны передавать обратные вызовы в функции. Написание асинхронного кода намного сложнее, чем синхронно. Даже при Promises, когда код огромен, становится сложно увидеть алгоритм (ну, это очень субъективно, с ним можно спорить, но для большинства программистов я думаю, что это правда). Поэтому мы хотим синхронно писать асинхронный код. То, что генераторы приходят нам на помощь. Поэтому вместо кода выше вы можете написать:
var ourImportantFunction = spawn(function*() {
//... some code 1
var val1 = yield task1();
//... some code 2
var val2 = yield task2(val1);
//... some code 3
var val3 = yield task3(val2);
return val3;
});
ourImportantFunction().then(callback);
где простейшая возможная реализация spawn
может быть примерно такой:
function spawn(generator) {
return function() {
var iter = generator.apply(this, arguments);
return Promise.resolve().then(function onValue(lastValue){
var result = iter.next(lastValue);
var done = result.done;
var value = result.value;
if (done) return value; // generator done, resolve promise
return Promise.resolve(value).then(onValue, iter.throw.bind(iter)); // repeat
});
};
}
Как видите, value
(результат некоторой асинхронной функции task{N}
) должен быть обещанием. Вы не можете сделать это с помощью обратных вызовов.
Остается только реализовать технику spawn
в самом языке. Таким образом, мы заменяем spawn
на async
и yield
на await
и переходим к ES7 async/await:
var ourImportantFunction = async function() {
//... some code 1
var val1 = await task1();
//... some code 2
var val2 = await task2(val1);
//... some code 3
var val3 = await task3(val2);
return val3;
}
Я рекомендую вам посмотреть это видео, чтобы больше понять это и некоторые другие приходящие методы. Если парень говорит слишком быстро для вас, замедлите скорость игры ( "настройки" в правом нижнем углу или просто нажмите [ shift
+ <
])
Что лучше: просто обратные вызовы или promises или Promises с генераторами - это очень субъективный вопрос. Обратные вызовы - это самое быстрое решение в настоящее время (производительность native Promises сейчас очень плохая). Promises с генераторами дает вам возможность синхронно писать асинхронный код. Но пока они намного медленнее, чем простые обратные вызовы.
Ответ 2
Promises, а генераторы - разные шаблоны (конструкции) программного обеспечения:
- http://en.wikipedia.org/wiki/Futures_and_promises
- http://en.wikipedia.org/wiki/Generator_(computer_programming)
На самом деле генераторы не являются асинхронными.
Генераторы полезны, когда вам нужно получить серию значений не сразу, а один за каждый запрос. Генератор будет возвращать следующее значение немедленно (синхронно) на каждый вызов до тех пор, пока он не достигнет конца последовательности (или бесконечный в случае бесконечных рядов).
Promises полезны, когда вам нужно "отложить" значение, которое еще не может быть вычислено (или может быть недоступно). Когда значение доступно - это целое значение (а не его часть), даже если это массив или другое сложное значение.
Вы можете увидеть более подробную информацию и примеры в статьях в Википедии.