You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: 5-network/03-fetch-progress/article.md
+14-22Lines changed: 14 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,10 +29,9 @@ while(true) {
29
29
}
30
30
```
31
31
32
-
نتیجهی فراخوانی `await reader.read()` یک شیء با دو ویژگی است:
33
-
34
-
* ویژگی **`done`** -- زمانی `true` میشود که خواندن کامل شده باشد، در غیر این صورت `false` است.
35
-
* ویژگی **`value`** -- یک آرایه تایپشده از بایتها: `Uint8Array`.
32
+
نتیجهی فراخوانی `await reader.read()` یک شیء با دو ویژگی است:
33
+
- ویژگی **`done`** -- زمانی `true` میشود که خواندن کامل شده باشد، در غیر این صورت `false` است.
34
+
- ویژگی **`value`** -- یک آرایه تایپشده از بایتها: `Uint8Array`.
36
35
37
36
```smart
38
37
توجه: Streams API همچنین پیمایش ناهمزمان (`async iteration`) روی `ReadableStream` را با حلقهی `for await..of` تعریف میکند، اما هنوز به طور گسترده پشتیبانی نمیشود (به [مشکلات مرورگرها](https://github.com/whatwg/streams/issues/778#issuecomment-461341033) مراجعه کنید)، بنابراین از حلقهی `while` استفاده میکنیم.
1. ما مانند حالت عادی `fetch` انجام میدهیم، اما به جای `response.json()`، یک stream reader میگیریم: `response.body.getReader()`.
92
90
93
-
توجه کنید که نمیتوان همزمان از هر دو روش برای خواندن یک پاسخ استفاده کرد: یا باید از reader استفاده کنیم یا از متدهای آمادهی response.
94
-
91
+
توجه کنید که نمیتوان همزمان از هر دو روش برای خواندن یک پاسخ استفاده کرد: یا باید از reader استفاده کنیم یا از متدهای آمادهی response.
95
92
2. قبل از خواندن، میتوانیم از هدر `Content-Length` طول کل پاسخ را به دست آوریم.
96
93
97
94
این مقدار ممکن است در درخواستهای cross-origin وجود نداشته باشد (به فصل <info:fetch-crossorigin> مراجعه کنید) و در عمل هم سرور مجبور به ارسال آن نیست. اما معمولاً وجود دارد.
98
-
99
95
3. تابع `await reader.read()` را تا زمانی که تمام شود اجرا میکنیم.
100
96
101
97
ما تکههای پاسخ را در آرایهی `chunks` جمع میکنیم. این مهم است چون بعد از مصرف شدن پاسخ، دیگر نمیتوان آن را دوباره با `response.json()` یا روشهای مشابه خواند (اگر امتحان کنید خطا خواهید گرفت).
102
-
103
98
4. در پایان، ما `chunks` را داریم -- آرایهای از قطعات بایت `Uint8Array`. باید آنها را به یک خروجی واحد تبدیل کنیم. متأسفانه متد مستقیمی برای اتصال آنها وجود ندارد، بنابراین این کار را دستی انجام میدهیم:
104
-
105
-
1. یک `Uint8Array` جدید با طول کل ایجاد میکنیم: `chunksAll = new Uint8Array(receivedLength)`
106
-
2. سپس با `.set(chunk, position)` هر قطعه را پشت سر هم داخل آن کپی میکنیم.
107
-
99
+
1. یک `Uint8Array` جدید با طول کل ایجاد میکنیم: `chunksAll = new Uint8Array(receivedLength)`
100
+
2. سپس با `.set(chunk, position)` هر قطعه را پشت سر هم داخل آن کپی میکنیم.
108
101
5. در نهایت دادهی نهایی در `chunksAll` قرار دارد، اما هنوز رشته نیست.
109
102
110
103
برای تبدیل به رشته، باید این بایتها را تفسیر کنیم. کلاس داخلی [TextDecoder](info:text-decoder) دقیقاً همین کار را انجام میدهد. سپس در صورت نیاز میتوانیم آن را با `JSON.parse` تبدیل کنیم.
111
104
112
105
اگر به جای رشته دادهی باینری بخواهیم، کار سادهتر است: کافی است مراحل 4 و 5 را با یک خط جایگزین کنیم:
113
-
114
-
```js
115
-
let blob =newBlob(chunks);
116
-
```
106
+
```js
107
+
let blob =newBlob(chunks);
108
+
```
117
109
118
110
در نهایت ما نتیجه را (به صورت رشته یا Blob) داریم و همزمان در طول فرایند، پیشرفت دانلود را هم دنبال میکنیم.
119
111
120
112
دوباره توجه کنید: این روش برای *پیشرفت آپلود* نیست (فعلاً با `fetch` ممکن نیست)، فقط برای *پیشرفت دانلود* است.
121
113
122
-
همچنین اگر اندازهی داده مشخص نباشد، باید در حلقه مقدار `receivedLength` را بررسی کنیم و اگر از یک حدی بیشتر شد، حلقه را متوقف کنیم تا آرایهی `chunks` باعث مصرف بیش از حد حافظه نشود.
114
+
همچنین اگر اندازهی داده مشخص نباشد، باید در حلقه مقدار `receivedLength` را بررسی کنیم و اگر از یک حدی بیشتر شد، حلقه را متوقف کنیم تا آرایهی `chunks` باعث مصرف بیش از حد حافظه نشود.
0 commit comments