потоковая передача ответа от Lambda с помощью InvokeWithResponseStreamCommand

У меня есть следующий код в приложении, реагирующем на реакцию, которое вызывает Lambda в моем клиенте AWS. Lambda срабатывает нормально, все журналы console.log отображаются правильно (200, правильный тип контента и т. д.), и я также вижу ответ от Lambda в CloudWatch, и это ожидаемый результат (потоковый ответ). . У меня также есть этот код, работающий в обычном React, и он тоже работает нормально, и я получаю ожидаемый результат.

Однако в React-Native ответ приходит по-другому и вызывает исключение, которое я не смог выяснить. Судя по этой документации AWS , в EventStream должно быть что-то (InvokeComplete, PayloadChunk), но судя по логам, я, похоже, ничего не получаю.

      import { Lambda, InvokeWithResponseStreamCommand, LambdaClient } from "@aws-sdk/client-lambda"
import "react-native-url-polyfill/auto";
import 'react-native-get-random-values'

async streamAWS(payload) {
    try {
        const lambda = new Lambda({
            region: 'us-west-1',
            credentials: {
                accessKeyId,
                secretAccessKey
            }
        });

        return lambda.send(new InvokeWithResponseStreamCommand(
            {
                FunctionName: 'test_stream',
                Payload: JSON.stringify({ payload })
            }
        ));
    } catch (error) {
        console.log(error);
    }
}

Это код, который я использую для извлечения потоковых данных. Как я уже сказал, этот код отлично работает в React Web, но не работает в React-Native:

      import { TextDecoder } from 'text-decoding';

useLayoutEffect(() => {
    async function stream() {
        const lambdaResponse = await awsService("payload");
        const decoder = new TextDecoder("utf-8");

        console.log(JSON.stringify(lambdaResponse));

        // this for causes the exception on React-Native
        for await (const event of lambdaResponse.EventStream) {
            const text = decoder.decode(event.PayloadChunk?.Payload);
            setTitle(oldText => oldText + text.replaceAll('"', ''));
        }
    }
    stream();
}, []);

Это ошибка, которую я получаю в React-Native:

      LOG response:
{"$metadata":{"httpStatusCode":200,"requestId":"b8eee2d1-a8e2-404f-9df3-dccb4810fdcd","attempts":1,"totalRetryDelay":0},"ExecutedVersion":"$LATEST","ResponseStreamContentType":"application/vnd.amazon.eventstream","EventStream":{},"StatusCode":200}
WARN Possible Unhandled Promise Rejection (id: 0):
TypeError: Object is not async iterable TypeError: Object is not async iterable

И я использую эту библиотеку и версию: "@aws-sdk/client-lambda": "3.335.0"

РЕДАКТИРОВАТЬ: Я также думаю, что основная проблема заключается в том, что свойство EventStream лямбда-ответа возвращается пустым , когда я вызываю его из собственного реагирования (вы можете увидеть это в разделе журнала EventStream:{}).

1 ответ

Кажется, чтоawait for ... ofсинтаксис не поддерживается в React Native. Самое простое решение — предоставить собственную функцию итератора. К счастью, спецификация итератора довольно проста; звонюnextвозвращает объект с двумя свойствами{ value, done }.valueнеудивительно, что это ваша следующая ценность.done— логическое значение, указывающее, завершился ли итератор, возвращая дополнительные значения.

Приведенная ниже функция возьмет итератор, соберет его значения и вернет их в виде массива.

      async function IteratorToArray(iterator) {

    const items = [];

    while (true) {
        const { value, done } = await iterator.next();
        if (done) {
            return items; // 'value' will be undefined on last iteration as it was 'done'
        } else {
            items.push(value);
        }
    }
}

Итак, для вашей проблемы вы можете назвать ее так:

      const lambdaResponse = await awsService("payload");

const data = await IteratorToArray(lambdaResponse.EventStream);

const decoder = new TextDecoder("utf-8");

for (const event of data) {
    const text = decoder.decode(event.PayloadChunk?.Payload);
    setTitle(oldText => oldText + text.replaceAll('"', ''));
}

Другие вопросы по тегам