<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Сетевые запросы on JSFlow</title><link>https://jsflow.ru/docs/network/</link><description>Recent content in Сетевые запросы on JSFlow</description><generator>Hugo</generator><language>ru</language><atom:link href="https://jsflow.ru/docs/network/index.xml" rel="self" type="application/rss+xml"/><item><title>Fetch API</title><link>https://jsflow.ru/docs/network/fetch/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/network/fetch/</guid><description>&lt;h1 id="fetch-api"&gt;
 Fetch API
 &lt;a class="anchor" href="#fetch-api"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Fetch&lt;/strong&gt; — современный способ отправить HTTP-запрос из браузера и получить &lt;code&gt;Response&lt;/code&gt;. Метод возвращает &lt;strong&gt;Promise&lt;/strong&gt;, поэтому его удобно сочетать с &lt;code&gt;async/await&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="простой-get-запрос"&gt;
 Простой GET-запрос
 &lt;a class="anchor" href="#%d0%bf%d1%80%d0%be%d1%81%d1%82%d0%be%d0%b9-get-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/tracks?limit=5&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;tracks&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;tracks&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;length&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;По умолчанию &lt;code&gt;fetch&lt;/code&gt; делает &lt;strong&gt;GET&lt;/strong&gt; без тела. URL может быть относительным (&lt;code&gt;/api/...&lt;/code&gt;) — браузер подставит origin текущей страницы.&lt;/p&gt;
&lt;p&gt;Если сервер отвечает не JSON, а текстом или файлом:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/export.csv&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;csv&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;response&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;text&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;hr&gt;
&lt;h2 id="разбор-json"&gt;
 Разбор JSON
 &lt;a class="anchor" href="#%d1%80%d0%b0%d0%b7%d0%b1%d0%be%d1%80-json"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;response.json()&lt;/code&gt; тоже возвращает Promise: тело читается асинхронно.&lt;/p&gt;</description></item><item><title>CORS и ошибки запросов</title><link>https://jsflow.ru/docs/network/cors/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/network/cors/</guid><description>&lt;h1 id="cors-и-ошибки-запросов"&gt;
 CORS и ошибки запросов
 &lt;a class="anchor" href="#cors-%d0%b8-%d0%be%d1%88%d0%b8%d0%b1%d0%ba%d0%b8-%d0%b7%d0%b0%d0%bf%d1%80%d0%be%d1%81%d0%be%d0%b2"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;CORS (Cross-Origin Resource Sharing)&lt;/strong&gt; — механизм браузера, который ограничивает чтение ответов на запросы к &lt;strong&gt;другому origin&lt;/strong&gt; (другой домен, порт или протокол). JavaScript на &lt;code&gt;https://shop.example&lt;/code&gt; не может свободно читать ответ от &lt;code&gt;https://api.other.com&lt;/code&gt;, пока сервер явно не разрешит это заголовками.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="origin-и-тот-же-сайт"&gt;
 Origin и «тот же сайт»
 &lt;a class="anchor" href="#origin-%d0%b8-%d1%82%d0%be%d1%82-%d0%b6%d0%b5-%d1%81%d0%b0%d0%b9%d1%82"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Origin = протокол + хост + порт:&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;URL страницы&lt;/th&gt;
					&lt;th&gt;URL API&lt;/th&gt;
					&lt;th&gt;Кросс-домен?&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://jsflow.dev/app&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;https://jsflow.dev/api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Нет&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://jsflow.dev/app&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;http://jsflow.dev/api&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Да (протокол)&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;&lt;code&gt;https://jsflow.dev/app&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;&lt;code&gt;https://api.jsflow.dev&lt;/code&gt;&lt;/td&gt;
					&lt;td&gt;Да (хост)&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;// same-origin — CORS не мешает читать ответ
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;home&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;fetch&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/config&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;config&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;await&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;home&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;json&lt;/span&gt;()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Запрос &lt;strong&gt;уходит&lt;/strong&gt; на другой origin, но если сервер не прислал разрешающие заголовки, &lt;strong&gt;скрипт не увидит тело ответа&lt;/strong&gt; — в консоли типичная ошибка про CORS policy.&lt;/p&gt;</description></item><item><title>WebSocket</title><link>https://jsflow.ru/docs/network/websocket/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/network/websocket/</guid><description>&lt;h1 id="websocket"&gt;
 WebSocket
 &lt;a class="anchor" href="#websocket"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;WebSocket&lt;/strong&gt; — протокол поверх TCP, который держит &lt;strong&gt;постоянное двустороннее&lt;/strong&gt; соединение между браузером и сервером. В отличие от &lt;a href="https://jsflow.ru/docs/network/fetch/"&gt;Fetch&lt;/a&gt;, сервер может сам отправить данные клиенту без нового HTTP-запроса — удобно для чатов, живых дашбордов и уведомлений о статусе заказа.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="создание-соединения"&gt;
 Создание соединения
 &lt;a class="anchor" href="#%d1%81%d0%be%d0%b7%d0%b4%d0%b0%d0%bd%d0%b8%d0%b5-%d1%81%d0%be%d0%b5%d0%b4%d0%b8%d0%bd%d0%b5%d0%bd%d0%b8%d1%8f"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;Клиентский API — глобальный конструктор &lt;code&gt;WebSocket&lt;/code&gt;. URL начинается с &lt;code&gt;ws://&lt;/code&gt; или &lt;code&gt;wss://&lt;/code&gt; (защищённый вариант, аналог HTTPS):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;socket&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;WebSocket&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;wss://jsflow.dev/ws/playlist&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;socket&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addEventListener&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;open&amp;#39;&lt;/span&gt;, () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Канал открыт&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;socket&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;addEventListener&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;message&amp;#39;&lt;/span&gt;, (&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;payload&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;log&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Новый трек:&amp;#39;&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;payload&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;title&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;})
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;После успешного handshake соединение остаётся открытым, пока одна из сторон не закроет его или не оборвётся сеть.&lt;/p&gt;</description></item><item><title>Server-Sent Events (EventSource)</title><link>https://jsflow.ru/docs/network/sse/</link><pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate><guid>https://jsflow.ru/docs/network/sse/</guid><description>&lt;h1 id="server-sent-events-eventsource"&gt;
 Server-Sent Events (EventSource)
 &lt;a class="anchor" href="#server-sent-events-eventsource"&gt;#&lt;/a&gt;
&lt;/h1&gt;
&lt;p&gt;&lt;strong&gt;Server-Sent Events (SSE)&lt;/strong&gt; — способ получать от сервера &lt;strong&gt;поток текстовых событий&lt;/strong&gt; по одному HTTP-соединению. Клиентский API — класс &lt;code&gt;EventSource&lt;/code&gt;: браузер сам переподключается и парсит формат &lt;code&gt;text/event-stream&lt;/code&gt;. Подходит для ленты активности, счётчиков на дашборде и статусов сборки — когда клиенту нужно только &lt;strong&gt;слушать&lt;/strong&gt;, без частых ответов серверу.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="базовое-подключение"&gt;
 Базовое подключение
 &lt;a class="anchor" href="#%d0%b1%d0%b0%d0%b7%d0%be%d0%b2%d0%be%d0%b5-%d0%bf%d0%be%d0%b4%d0%ba%d0%bb%d1%8e%d1%87%d0%b5%d0%bd%d0%b8%d0%b5"&gt;#&lt;/a&gt;
&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-js" data-lang="js"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#66d9ef"&gt;new&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;EventSource&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;/api/dashboard/activity&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;onmessage&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; (&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;) =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#66d9ef"&gt;const&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;row&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; &lt;span style="color:#a6e22e"&gt;JSON&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;parse&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;event&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;data&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;appendActivityRow&lt;/span&gt;(&lt;span style="color:#a6e22e"&gt;row&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;user&lt;/span&gt;, &lt;span style="color:#a6e22e"&gt;row&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;action&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#a6e22e"&gt;feed&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;onerror&lt;/span&gt; &lt;span style="color:#f92672"&gt;=&lt;/span&gt; () =&amp;gt; {
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt; &lt;span style="color:#a6e22e"&gt;console&lt;/span&gt;.&lt;span style="color:#a6e22e"&gt;warn&lt;/span&gt;(&lt;span style="color:#e6db74"&gt;&amp;#39;Поток активности прерван, EventSource переподключится&amp;#39;&lt;/span&gt;)
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Первый аргумент — URL (обычно same-origin). В отличие от &lt;code&gt;fetch&lt;/code&gt;, соединение остаётся открытым: сервер периодически дописывает строки в тело ответа.&lt;/p&gt;</description></item></channel></rss>