Ответ 1
По-видимому, выход - это синтаксический сахар для того, чтобы обернуть то, что он возвращает в обратном вызове, и соответствующим образом присвоить значение результата (и, по крайней мере, в случае co, выбросив аргумент ошибки в обратный вызов)
Нет, yield
не является синтаксическим сахаром. Это основной синтаксический элемент генераторов. Когда этот генератор создается, вы можете запустить его (вызывая .next()
на нем), и это вернет значение, которое было return
ed или yield
ed. Когда генератор был yield
ed, вы можете продолжить его позже, снова вызвав .next()
. Аргументами для next
будет значение, возвращаемое выражением yield
внутри генератора.
Только в случае co
эти асинхронные функции обратного вызова (и другие вещи) обрабатываются "соответственно" для того, что вы считаете естественным в библиотеке потоков асинхронного управления.
Что делается, когда используется доход?
Пример функции thread
из статьи которую вы читаете, дает вам хорошее представление об этом:
function thread(fn) {
var gen = fn();
function next(err, res) {
var ret = gen.next(res);
if (ret.done) return;
ret.value(next);
}
next();
}
В вашем коде yield
выводит значение выражения read("file")
из генератора при его запуске. Это становится ret.val
, результатом gen.next()
. Для этого передается функция next
- обратный вызов, который будет продолжать генератор с помощью res
ult, который был передан ему. В коде генератора выглядит так, как если бы выражение yield
возвращало это значение.
"Развернутая" версия происходящего может быть написана следующим образом:
function fn*() {
console.log( yield function (done) {
fs.readFile("filepath", "file", done);
} );
}
var gen = fn();
var ret1 = gen.next();
var callasync = ret1.value;
callasync(function next(err, res) {
var ret2 = gen.next(res); // this now does log the value
ret2.done; // true now
});