#javascript #typescript #generator
#javascript #typescript #генератор
Вопрос:
scenario.ts
export interface Step {
text: string;
image: string;
time: number
}
export interface IScenario {
name: string;
steps: Array<Step>;
}
Restaurant.ts
import {IScenario, Step} from './interfaces/scenario'
export default class Restaurant implements IScenario {
name: string = 'Приключение в ресторане';
steps: Array<Step> = [
{
text: 'Вы пришли в ресторан',
image: 'https://sun9-3.userapi.com/55H3n5pt-TvwwdQzmpBZ9mcHURCqf85x1mXvlw/oyI4OlFu3R0.jpg',
time: 2000,
},
{
text: 'Перед вами стоит стол',
image: '',
time: 5000,
},
];
private *enumerateSteps(steps: Array<Step>): IterableIterator<Step> {
yield step;
}
start(): void {
for (const step of this.enumerateSteps(this.steps)) {
setTimeout(() => {
return console.log(step.text);
step.next();
}, step.time);
}
}
}
Я хочу получить следующий шаг через некоторое время, но получаю сообщение об ошибке:
Свойство ‘next’ не существует для типа ‘Step’.
И у меня также есть ошибка об отсутствии step
по какой-то причине, но я не знаю почему.
Комментарии:
1. » ошибка об отсутствии
step
по какой-то причине » — да, вstep
вашем методе не определена переменнаяenumerateSteps
. Что вы ожидали, что это будет? Обратите внимание, что вы также нигде не используете аргументsteps
. (Но это не похоже на опечатку, поскольку они имеют разные типы).2. Я хочу получить настоящее
step
в каждом случае. Я попытался обновить генераторconst current = steps[0]; yield current;
, но все равно получаю сообщение об ошибке «Свойство ‘next’ не существует для типа ‘Step’:3. Похоже, вы пытаетесь асинхронно выполнить итерацию по своему генератору. В этом случае, как отметил @Bergi, в нем нет необходимости, но язык допускает асинхронные взаимодействия .
4. Ответ Берги отличный, но еще одна проблема с вашим кодом — если вы
yield
используете функцию генератора только один раз (не в цикле), вы выполняете итерацию только один раз. Другими словами,[...({ *[Symbol.iterator]() { yield 1 } })]
просто[1]
.5. Спасибо всем 🙂
Ответ №1:
Вы вообще не должны использовать генераторы здесь. То, что вы хотите, может быть выполнено с помощью подхода, основанного на обратном вызове
start(callback?: () => void): void {
this.steps.reduceRight((next, step) => () => {
console.log(step.text);
setTimeout(next, step.time);
}, () => {
console.log('All steps done');
callback?.();
})();
}
или с помощью обещаний и async
/ await
:
async start(): Promise<void> {
for (const step of this.steps) {
console.log(step.text);
await new Promise(resolve => setTimeout(resolve, step.time));
}
console.log('All steps done');
}