Он говорит мне: «TypeError: Foo.my_method(...) не является функцией или ее возвращаемое значение не является асинхронным итерируемым». Как сделать так?
class Foo {
constructor() {
return (async () => { this.sleep(1000) })()
}
async *my_method(message) {
let pos = 0
while (true) {
yield message.charAt(pos)
await this.sleep(100)
pos += 1
}
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
let foo = new Foo().then(async () => {
for await (let msg of foo.my_method("AAAA")) {
msgs.push(msg)
}
})
Просто исправьте то, что вы ввели как ...
. Если этого объяснения недостаточно, то используйте не ...
, а минимально воспроизводимый пример.
Теперь это воспроизводимо
constructor() { return (async () => { this.sleep(1000) })() }
было СУПЕР ВАЖНО! Ваш первоначальный код был похож на то, как вы пришли к автомеханику и сказали: «Кажется, у моей машины проблемы с запуском». И ты не показываешь машину, просто рассказываешь ему, что ты пробовал. Зарядка аккумулятора, замена масла, ходовая диагностика. Но опуская тот факт, что это была не машина, а кусок сыра, с которым вы пытались это сделать. Который на самом деле не работает, как автомобиль. Или вообще. Потому что вы переопределили конструктор, чтобы он возвращал что-то, что не является экземпляром вашего класса.
да, извини, я был таким глупым
метод this.my = асинхронная функция(){...}
Попробуйте так
Теперь он кричит на мою доходность с помощью «SyntaxError: неожиданное зарезервированное слово строгого режима»
Асинхронные функции не являются итерируемыми.
Делает
let foo = new Foo().then(
установит foo как Promise, поэтому вы не можете сделать foo.my_method()
Я думаю, что вы пытаетесь сделать следующее:
class Foo {
load(){
return Promise.resolve()
}
async *my_method(message) {
let pos = 0
while (pos < message.length) {
yield await this.sleep(100).then(() => message.charAt(pos))
pos += 1
}
}
sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
(async function(){
let foo = new Foo()
await foo.load()
const msg = []
for await (const data of foo.my_method("ABCD")) {
msg.push(data)
}
console.info(msg)
})()
Я только что добавил условие в while
, чтобы ваш генератор завершал работу в какой-то момент, и я поместил асинхронный цикл в (асинхронный) IFEE, чтобы генератор можно было ожидать напрямую (похоже, это то, что вы пытались делать).
Это работает для вас? Дайте мне знать, если это имеет смысл.
Мне нужно подождать, пока конструктор закончит свою работу, это занимает некоторое время, похоже, это мой настоящий вопрос
Я не думаю, что имеет смысл писать конструктор, который нужно ждать. Если вам нужно дождаться данных, прежде чем вы сможете создать экземпляр объекта, сделайте это, то есть fetch().then(data => new Foo(data))
. Это даст вам больше гибкости и не привязывает ваш класс к тому, как вы извлекаете его данные.
Хорошо, спасибо, я переместил все долгоиграющие вещи в другой метод инициализации, и теперь он работает.
@rigiva «Мне нужно подождать, пока конструктор закончит свою работу, это занимает некоторое время, похоже, это мой настоящий вопрос» Да, это называется XY-проблема.
возвращать асинхронную функцию из конструктора нельзя. в чистом js это что-то сделало бы (вообще бесполезно в примере из вопроса), но ts просто не позволит этому случиться, не поставив any
fo типа.
Я думаю, вы реализуете какую-то коллекцию, и это способ сделать асинхронную итерируемую коллекцию.
class Foo {
constructor(private message: string) {}
async *[Symbol.asyncIterator]() {
let pos = 0
while (this.message[pos]) {
yield this.message.charAt(pos)
await this.sleep(100)
pos += 1
}
}
sleep(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
}
async function userCode() {
let foo = new Foo('xxx');
const msgs = [];
for await (let msg of foo) {
msgs.push(msg)
}
console.info(msgs);
}
объявив Symbol.asyncIterator
в классе, все экземпляры будут асинхронно повторяемыми
Предоставьте реальный минимальный воспроизводимый пример или более полный код для конкретной помощи. Но в теории это работает нормально. jsfiddle