Комбинация генератор + обещание; объяснение потока управления
Используя некоторый код, найденный по адресу https://www.promisejs.org/generators/, я собрал этот тестовый сценарий (возможно, он не актуален, но я запускаю его, выполнив regenerator --include-runtime gentest.js > gentest-out.js && node gentest-out.js
):
function async(makeGenerator){
return function () {
var generator = makeGenerator.apply(this, arguments);
function handle(result){
// result => { done: [Boolean], value: [Object] }
console.log(' entered handle, result:', result);
if (result.done) {
console.log(' done, returning result.value:', result.value);
return Promise.resolve(result.value);
}
console.log(' not done yet, returning promise');
return Promise.resolve(result.value).then(function (res){
console.log(' inside then.. res is', res);
var me = generator.next(res);
console.log(' generator.next(' + res + ') =', me);
return handle(me);
}, function (err){
return handle(generator.throw(err));
});
}
try {
return handle(generator.next());
} catch (ex) {
return Promise.reject(ex);
}
}
}
var get = async(function*() {
var left = new Promise(function(resolve,reject) {
console.log('in promise object');
setTimeout(function() {
console.log(' in promise timeout function');
setTimeout(function() {
console.log(' in second timeout function');
resolve(1)
}, 10000);
}, 3000)
});
console.log('got to before right=5');
var right = 5;
console.log('yield left:', yield left);
console.log('got to after yield left');
console.log('yield right:', yield right);
console.log('returning');
return
});
console.log('get is instance of Promise before call:', get instanceof Promise)
console.log('get is instance of promise once called:', get() instanceof Promise);
Результат:
get is instance of Promise before call: false
in promise object
got to before right=5
entered handle, result: { value: {}, done: false }
not done yet, returning promise
get is instance of promise once called: true
<long pause here>
in promise timeout function
<longer pause here>
in second timeout function
inside then.. res is 1
yield left: 1
got to after yield left
generator.next(1) = { value: 5, done: false }
entered handle, result: { value: 5, done: false }
not done yet, returning promise
inside then.. res is 5
yield right: 5
returning
generator.next(5) = { value: undefined, done: true }
entered handle, result: { value: undefined, done: true }
done, returning result.value: undefined
Мои вопросы:
- Почему
result.value
начальногоgenerator.next()
вызов равен{}
? Разве это не должен быть объект Promise, назначенный слева? - Кажется, что
Promise.resolve(result.value)
внутри ручки есть функция блокировки. Я ожидал, что обещание будет возвращено, пока метод.then выполняется на следующем тике. Вместо этого кажется, чтоPromise.resolve
не теряет контроль, пока обратный вызов метода.then не выполнитresolve(1)
, Это то, что здесь происходит? Редактировать - я думаю. Затем выполняется на следующем тике, но в цикле событий больше ничего нет, поэтому он выглядит блокирующим... но он все равно не объясняет, почему объект Promise не возвращается немедленно.