SUPER_OLEG_DEV Telegram 131
Переходим к телепортации промисов с сервера на клиент.

В первую очередь, мне очень комфортно работать с паттерном Deferred и он отлично подходит для этой задачи:


class Deferred {
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = (data) => {
this.resolveData = data;
resolve(data);
};
this.reject = (reason) => {
this.rejectReason = reason;
reject(reason);
};
});
}

isResolved() {
return typeof this.resolveData !== 'undefined';
}

isRejected() {
return typeof this.rejectReason !== 'undefined';
}
}

На сервере, на каждое асинхронное действие, которое мы пометим как отложенное, необходимо создать свой экземпляр Deferred промиса, и выполнить его resolve/reject по завершению соответствующей асинхронной задачи.

Этот паттерн позволит не ждать сайд-эффект сразу, но подписаться на его выполнение позже, псевдо-код:

async function runDeferredAction() {
deferred = new Deferred()

// допустим этот асинхронный метод выполняется 5 секунд
someLongAction
.then(deferred.resolve)
.catch(deferred.reject)
}

async function render() {
// запускаем сайд эффекты, runDeferredAction резолвится сразу и не блокирует ответ
await promiseAll([
runAnyAction(),
runAnyAction(),
runDeferredAction()
])

// запускаем рендер в стрим
reactRenderToStream()

// ждем отложенный экшен
await deferred.promise

// телепортируем промис
...

// закрываем стрим
closeStream()
}

В качестве механизма для отложенной загрузки данных показалось хорошим решением использовать уже существующие трамвайные Actions - наш основной инструмент для создания и выполнения сайд-эффектов.

В отличие от функций - загрузчиков данных в Remix или SvelteKit, на одну страницу трамвай позволяет запустить множество параллельных экшенов, также мы обычно не используем данные из экшенов напрямую, а передаем их с сервера на клиент через трамвайные сторы.

Для новых deferred экшенов оказалось проще все-таки использовать их напрямую для получения данных, что бы не усложнять “телепортацию” и не добавлять новых API (еще раздумываю над этим решением).

Итак, у нас есть набор страничных экшенов, некоторые из них помечены как deferred, опишу механизм телепортации:

- трамвай не ждет выполнения deferred экшенов перед рендерингом страницы на сервере
- на каждый такой экшен создается инстанс new Deferred(), который будет зарезолвлен после резолва самого экшена
- на клиент в head передается инлайн скрипт вида <script>window.DEFERRED_MAP['actionName'] = new Deferred()</script> - то есть название экшена и становится уникальным ключем и таким “мостом” между сервером и клиентом
- после резолва экшена, на клиент передается инлайн скрипт с резолвом промиса с соответствующими данными (их обернул в защиту от XSS атак) - <script>window.DEFERRED_MAP['actionName'].resolve(SANITIZED_ACTION_DATA)</script>

Таким образом, промис на клиенте будет зарезолвлен практически сразу после того как это произойдет на сервере.
👍9🔥2



tgoop.com/super_oleg_dev/131
Create:
Last Update:

Переходим к телепортации промисов с сервера на клиент.

В первую очередь, мне очень комфортно работать с паттерном Deferred и он отлично подходит для этой задачи:


class Deferred {
constructor() {
this.promise = new Promise((resolve, reject) => {
this.resolve = (data) => {
this.resolveData = data;
resolve(data);
};
this.reject = (reason) => {
this.rejectReason = reason;
reject(reason);
};
});
}

isResolved() {
return typeof this.resolveData !== 'undefined';
}

isRejected() {
return typeof this.rejectReason !== 'undefined';
}
}

На сервере, на каждое асинхронное действие, которое мы пометим как отложенное, необходимо создать свой экземпляр Deferred промиса, и выполнить его resolve/reject по завершению соответствующей асинхронной задачи.

Этот паттерн позволит не ждать сайд-эффект сразу, но подписаться на его выполнение позже, псевдо-код:

async function runDeferredAction() {
deferred = new Deferred()

// допустим этот асинхронный метод выполняется 5 секунд
someLongAction
.then(deferred.resolve)
.catch(deferred.reject)
}

async function render() {
// запускаем сайд эффекты, runDeferredAction резолвится сразу и не блокирует ответ
await promiseAll([
runAnyAction(),
runAnyAction(),
runDeferredAction()
])

// запускаем рендер в стрим
reactRenderToStream()

// ждем отложенный экшен
await deferred.promise

// телепортируем промис
...

// закрываем стрим
closeStream()
}

В качестве механизма для отложенной загрузки данных показалось хорошим решением использовать уже существующие трамвайные Actions - наш основной инструмент для создания и выполнения сайд-эффектов.

В отличие от функций - загрузчиков данных в Remix или SvelteKit, на одну страницу трамвай позволяет запустить множество параллельных экшенов, также мы обычно не используем данные из экшенов напрямую, а передаем их с сервера на клиент через трамвайные сторы.

Для новых deferred экшенов оказалось проще все-таки использовать их напрямую для получения данных, что бы не усложнять “телепортацию” и не добавлять новых API (еще раздумываю над этим решением).

Итак, у нас есть набор страничных экшенов, некоторые из них помечены как deferred, опишу механизм телепортации:

- трамвай не ждет выполнения deferred экшенов перед рендерингом страницы на сервере
- на каждый такой экшен создается инстанс new Deferred(), который будет зарезолвлен после резолва самого экшена
- на клиент в head передается инлайн скрипт вида <script>window.DEFERRED_MAP['actionName'] = new Deferred()</script> - то есть название экшена и становится уникальным ключем и таким “мостом” между сервером и клиентом
- после резолва экшена, на клиент передается инлайн скрипт с резолвом промиса с соответствующими данными (их обернул в защиту от XSS атак) - <script>window.DEFERRED_MAP['actionName'].resolve(SANITIZED_ACTION_DATA)</script>

Таким образом, промис на клиенте будет зарезолвлен практически сразу после того как это произойдет на сервере.

BY SuperOleg dev notes


Share with your friend now:
tgoop.com/super_oleg_dev/131

View MORE
Open in Telegram


Telegram News

Date: |

Telegram Channels requirements & features Add up to 50 administrators During a meeting with the president of the Supreme Electoral Court (TSE) on June 6, Telegram's Vice President Ilya Perekopsky announced the initiatives. According to the executive, Brazil is the first country in the world where Telegram is introducing the features, which could be expanded to other countries facing threats to democracy through the dissemination of false content. Each account can create up to 10 public channels
from us


Telegram SuperOleg dev notes
FROM American