Просмотр кода
Прежде всего, избавьтесь от этого; это ничего не делает
const result = yield Promise.resolve('foobar').then(res => res);
Ваш генератор работает нормально
Если я запускаю этот генератор со следующей строкой, он регистрирует undefined
Нет, это не так. Он будет регистрировать {next, value}
каждый раз
function* testGenerator() {
const result = yield Promise.resolve('foobar');
console.log(result);
}
let test = testGenerator()
console.log(test.next())
// { value: Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1}, done: false }
console.log(test.next())
// { value: undefined, done: true }
Регистрация промисов сложна. Если вы мне не верите, посмотрите это
function* testGenerator() {
const result = yield Promise.resolve('foobar');
console.log(result);
}
let test = testGenerator()
test.next().value.then(console.log)
// "foobar"
Сопрограммы
Но в саге такие строки будут логироваться foobar. Мне просто любопытно, какой механизм стоит за этим (присвоение результата yield переменной)
Redux Saga построена так, чтобы проходить через генератор и обрабатывать различные эффекты. Обещание — это лишь одна из многих вещей, которые вы можете дать.
Вот пример простой функции сопрограммы, которая принимает экземпляр генератора и ожидает, что промисы будут возвращены до последнего результата. Обратите внимание на двусторонний поток данных.
yield
отправляет данные из генератора
gen.next(x)
отправляет следующее значение в генератор
Таким образом, мы используем эту возможность генераторов для отправки промиса out и отправки значения resolved промиса обратно in, что позволяет разрешенному промису значение, которое будет присвоено непосредственно переменной
const coro = gen => {
const next = x => {
const {value, done} = gen.next(x)
if (done)
return value
else
return value.then(next)
}
return next()
}
function* testGenerator () {
const x = yield Promise.resolve(1)
console.log(x) // 1
const y = yield Promise.resolve(2)
console.log(y) // 2
const z = yield Promise.resolve(3)
console.log(z) // 3
return x + y + z
}
coro(testGenerator()).then(console.log)
// "6"
async
и await
И теперь, когда вы это понимаете, вы понимаете точно, как работают предлагаемые async
/await
— функциональность следующего фрагмента может различаться в зависимости от поддержки вашего браузера.
Изменения:
- нам больше не нужен помощник
coro
- используйте ключевое слово
async
вместо генератора function*
- используйте ключевое слово
await
вместо yield
Поведение такое же.
- используйте
await
, чтобы отправить обещание
- Разрешенное значение обещания отправляется обратно в качестве возвращаемого значения вызова
await
- Функции
async
неявно возвращают Promise, поэтому цепочка вызовов .then
позволяет получить окончательное значение.
const testRoutine = async () => {
const x = await Promise.resolve(1)
console.log(x) // 1
const y = await Promise.resolve(2)
console.log(y) // 2
const z = await Promise.resolve(3)
console.log(z) // 3
return x + y + z
}
testRoutine().then(console.log)
// "6"
Доморощенные сопрограммы
Вы не должны запускать свои собственные сопрограммы, потому что есть много вещей, на которые нужно обратить внимание. Например, если генератор выдает throw
s ошибку или yield
s отклоненное обещание, приведенная выше реализация просто проглотит его.
В демонстрационных целях я покажу вам, как это сделать, но если вы хотите охватить все свои основы, вам следует прочитать исходный код Redux Saga или исходный код код другой библиотеки сопрограмм, такой как tj/co
const coro = gen => {
return new Promise((resolve, reject) => {
const next = x => {
try {
let {value, done} = gen.next(x)
return done ? resolve(value) : value.then(next, reject)
}
catch (err) {
reject(err)
}
}
next()
})
}
function* noYield() { return 5 }
function* throwsUp() { throw Error("OOPS") }
function* yieldReject() { yield Promise.reject('NO') }
function* normal() { let x = yield Promise.resolve(16); return x * x; }
coro(noYield())
.then(console.log, console.error) // 5
coro(throwsUp())
.then(console.log, console.error) // [Error: OOPS]
coro(yieldReject())
.then(console.log, console.error) // "NO"
coro(normal())
.then(console.log, console.error) // 256
person
Mulan
schedule
28.02.2017
yield
возвращает все, что переданоnext()
. Вы ничего не проходите. - person a better oliver   schedule 28.02.2017