ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ ÑÑеÑаÑоÑи дозволÑÑÑÑ Ð½Ð°Ð¼ пеÑебиÑаÑи данÑ, ÑÐºÑ Ð½Ð°Ð´Ñ Ð¾Ð´ÑÑÑ Ð°ÑÐ¸Ð½Ñ Ñонно, на вимогÑ. ÐапÑиклад, коли ми заванÑажÑÑмо ÑоÑÑ ÑаÑÑинами ÑеÑез меÑежÑ. РаÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи ÑоблÑÑÑ Ñе Ñе зÑÑÑнÑÑе.
ÐавайÑе ÑпоÑаÑÐºÑ ÑозглÑнемо пÑоÑÑий пÑиклад, Ñоб зÑозÑмÑÑи ÑинÑакÑиÑ, а поÑÑм ÑозглÑнемо ÑеалÑний ваÑÑÐ°Ð½Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑаннÑ.
ÐÑигадÑÐ²Ð°Ð½Ð½Ñ ÑÑеÑаÑоÑÑв
Ðгадаймо ÑÐµÐ¼Ñ Ð¿Ñо ÑÑеÑаÑоÑи.
ÐÐ´ÐµÑ Ð¿Ð¾Ð»ÑÐ³Ð°Ñ Ð² ÑомÑ, Ñо ми маÑмо обâÑкÑ, напÑиклад, range:
let range = {
from: 1,
to: 5
};
â¦Ð ми Ñ
оÑÑли б викоÑиÑÑовÑваÑи Ð´Ð»Ñ Ð½Ñого Ñикл for..of, напÑиклад, for(value of range), Ñоб оÑÑимаÑи знаÑÐµÐ½Ð½Ñ Ð²Ñд 1 до 5.
ÐнакÑе кажÑÑи, ми Ñ Ð¾Ñемо додаÑи до обâÑкÑа можливÑÑÑÑ Ð¿ÐµÑебиÑÐ°Ð½Ð½Ñ (ÑÑеÑаÑÑÑ).
Це можна ÑеалÑзÑваÑи за Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÑпеÑÑалÑного меÑÐ¾Ð´Ñ Ð· Ð½Ð°Ð·Ð²Ð¾Ñ Symbol.iterator:
- Цей меÑод викликаÑÑÑÑÑ ÐºÐ¾Ð½ÑÑÑÑкÑÑÑÑ
for..of, коли запÑÑкаÑÑÑÑÑ Ñикл, Ñ Ð²Ñн повинен повеÑнÑÑи обâÑÐºÑ Ñз меÑодомnext. - Ðа кожнÑй ÑÑеÑаÑÑÑ Ð²Ð¸ÐºÐ»Ð¸ÐºÐ°ÑÑÑÑÑ Ð¼ÐµÑод
next(), Ñоб оÑÑимаÑи наÑÑÑпне знаÑеннÑ. next()Ð¼Ð°Ñ Ð¿Ð¾Ð²ÐµÑÑаÑи знаÑÐµÐ½Ð½Ñ Ñ ÑоÑмÑ{done: true/false, value:<loop value>}, деdone:trueознаÑÐ°Ñ ÐºÑнеÑÑ ÑиклÑ.
ÐÑÑ ÑеалÑзаÑÑÑ Ð¾Ð±âÑкÑа range, Ñо пеÑебиÑаÑÑÑÑÑ:
let range = {
from: 1,
to: 5,
[Symbol.iterator]() { // викликаÑÑÑÑÑ Ð¾Ð´Ð¸Ð½ Ñаз, на поÑаÑÐºÑ for..of
return {
current: this.from,
last: this.to,
next() { // викликаÑÑÑÑÑ ÐºÐ¾Ð¶Ð½Ñ ÑÑеÑаÑÑÑ, Ñоб оÑÑимаÑи наÑÑÑпне знаÑеннÑ
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
}
};
for(let value of range) {
alert(value); // 1, поÑÑм 2, поÑÑм 3, поÑÑм 4, поÑÑм 5
}
ЯкÑо ÑоÑÑ Ð½ÐµÐ·ÑозÑмÑло, вÑдвÑдайÑе ÑоздÑл ÐÑеÑаÑÐ¸Ð²Ð½Ñ Ð¾Ð±âÑкÑи, Ñ Ð½ÑÐ¾Ð¼Ñ Ð½Ð°Ð²ÐµÐ´ÐµÐ½Ð¾ вÑÑ ÑнÑоÑмаÑÑÑ Ð¿Ñо звиÑÐ°Ð¹Ð½Ñ ÑÑеÑаÑоÑи.
ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ ÑÑеÑаÑоÑи
ÐÑинÑ
Ñонна ÑÑеÑаÑÑÑ Ð¿Ð¾ÑÑÑбна ÑодÑ, коли знаÑÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ
одÑÑÑ Ð°ÑинÑ
Ñонно: пÑÑÐ»Ñ setTimeout або ÑнÑого Ð²Ð¸Ð´Ñ Ð·Ð°ÑÑимки.
ÐайпоÑиÑенÑÑий випадок полÑÐ³Ð°Ñ Ð² ÑомÑ, Ñо обâÑкÑÑ Ð¿Ð¾ÑÑÑбно зÑобиÑи меÑежевий Ð·Ð°Ð¿Ð¸Ñ Ð´Ð»Ñ Ð´Ð¾ÑÑÐ°Ð²Ð»ÐµÐ½Ð½Ñ Ð½Ð°ÑÑÑпного знаÑеннÑ. РеалÑний пÑиклад ÑÑого ми побаÑимо ÑÑÐ¾Ñ Ð¸ пÑзнÑÑе.
ÐÐ»Ñ Ñого, Ñоб пеÑебиÑаÑи обâÑÐºÑ Ð°ÑÐ¸Ð½Ñ Ñонно:
- ÐикоÑиÑÑовÑйÑе
Symbol.asyncIteratorзамÑÑÑÑSymbol.iterator. - ÐеÑод
next()повинен повеÑÑаÑи пÑомÑÑ (Ñкий Ð¼Ð°Ñ Ð¼ÑÑÑиÑи наÑÑÑпне знаÑеннÑ).- Це ÑобиÑÑÑÑ Ð·Ð° Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÐºÐ»ÑÑового Ñлова
async. ÐÑÑ Ñак:async next().
- Це ÑобиÑÑÑÑ Ð·Ð° Ð´Ð¾Ð¿Ð¾Ð¼Ð¾Ð³Ð¾Ñ ÐºÐ»ÑÑового Ñлова
- Щоб пеÑебÑаÑи Ñакий обâÑкÑ, ми Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑваÑи Ñикл
for await (let item of iterable).- ÐвеÑнÑÑÑ ÑÐ²Ð°Ð³Ñ Ð½Ð° Ñлово
await.
- ÐвеÑнÑÑÑ ÑÐ²Ð°Ð³Ñ Ð½Ð° Ñлово
Як поÑаÑковий пÑиклад, ÑÑвоÑÑмо обâÑÐºÑ range, Ñо пеÑебиÑаÑÑÑÑÑ. ÐÑн бÑде подÑбний до попеÑеднÑого, пÑоÑе повеÑÑаÑиме знаÑÐµÐ½Ð½Ñ Ð°ÑинÑ
Ñонно â по Ð¾Ð´Ð½Ð¾Ð¼Ñ Ð·Ð° ÑекÑндÑ.
ÐÑе, Ñо нам поÑÑÑбно зÑобиÑи â Ñе внеÑÑи кÑлÑка замÑн Ñ ÐºÐ¾Ð´Ñ Ð²Ð¸Ñе:
let range = {
from: 1,
to: 5,
[Symbol.asyncIterator]() { // (1)
return {
current: this.from,
last: this.to,
async next() { // (2)
// пÑимÑÑка: ми можемо викоÑиÑÑаÑи "await" вÑеÑÐµÐ´Ð¸Ð½Ñ Ð°ÑинÑ
Ñонного next:
await new Promise(resolve => setTimeout(resolve, 1000)); // (3)
if (this.current <= this.last) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
}
};
(async () => {
for await (let value of range) { // (4)
alert(value); // 1,2,3,4,5
}
})()
Як баÑимо, ÑÑÑÑкÑÑÑа ÑÑ Ð¾Ð¶Ð° на звиÑÐ°Ð¹Ð½Ñ ÑÑеÑаÑоÑи:
- Щоб обâÑÐºÑ Ð¿ÐµÑебиÑавÑÑ Ð°ÑинÑ
Ñонно, вÑн повинен маÑи меÑод
Symbol.asyncIterator(1). - Цей меÑод повинен повеÑÑаÑи обâÑÐºÑ Ñз меÑодом
next(), Ñкий повеÑÑÐ°Ñ Ð¿ÑомÑÑ(2). - ÐеÑод
next()не повинен бÑÑиasync, Ñе може бÑÑи звиÑайний меÑод, Ñо повеÑÑÐ°Ñ Ð¿ÑомÑÑ, алеasyncдозволÑÑ Ð½Ð°Ð¼ викоÑиÑÑовÑваÑиawait, ÑÐ¾Ð¼Ñ Ñе зÑÑÑно. ТÑÑ Ð¼Ð¸ пÑоÑÑо заÑÑимÑÑмоÑÑ Ð½Ð° ÑекÑндÑ(3). - ÐÐ»Ñ ÑÑеÑаÑÑÑ Ð¼Ð¸ викоÑиÑÑовÑÑмо
for await(let value of range)(4), а Ñаме додаÑмо âawaitâ пÑÑÐ»Ñ âforâ. ÐÑн викликаÑrange[Symbol.asyncIterator]()один Ñаз, а поÑÑм йогоnext()Ð´Ð»Ñ Ð·Ð½Ð°ÑенÑ.
ÐÑÑ Ð½ÐµÐ²ÐµÐ»Ð¸ÐºÐ° ÑаблиÑÑ Ð· вÑдмÑнноÑÑÑми:
| ÐÑеÑаÑоÑи | ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ ÑÑеÑаÑоÑи | |
|---|---|---|
| ÐеÑод Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑÐµÐ½Ð½Ñ ÑÑеÑаÑоÑа | Symbol.iterator |
Symbol.asyncIterator |
next() повеÑÑÐ°Ñ |
бÑдÑ-Ñке знаÑÐµÐ½Ð½Ñ | Promise |
| Ð´Ð»Ñ ÑÐ¸ÐºÐ»Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑйÑе | for..of |
for await..of |
... не пÑаÑÑÑ Ð°ÑинÑ
ÑонноФÑнкÑÑÑ, Ñо вимагаÑÑÑ Ð·Ð²Ð¸ÑÐ°Ð¹Ð½Ñ ÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ ÑÑеÑаÑоÑи, не пÑаÑÑÑÑÑ Ð· аÑÐ¸Ð½Ñ Ñонними.
ÐапÑиклад, не бÑде пÑаÑÑваÑи ÑинÑакÑÐ¸Ñ ÑозÑиÑеннÑ:
alert( [...range] ); // Ðомилка, Ð½ÐµÐ¼Ð°Ñ Symbol.iterator
Це пÑиÑодно, оÑкÑлÑки вÑн оÑÑкÑÑ Ð·Ð½Ð°Ð¹Ñи Symbol.iterator, а не Symbol.asyncIterator.
Це Ñакож ÑÑоÑÑÑÑÑÑÑ for..of: ÑинÑакÑÐ¸Ñ Ð±ÐµÐ· await поÑÑебÑÑ Symbol.iterator.
ÐÑигадÑÐ²Ð°Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑÑв
Ð¢ÐµÐ¿ÐµÑ Ð·Ð³Ð°Ð´Ð°Ð¹Ð¼Ð¾ генеÑаÑоÑи, оÑкÑлÑки вони дозволÑÑÑÑ Ð·ÑобиÑи ÑÑеÑаÑивний код знаÑно коÑоÑÑим. У бÑлÑÑоÑÑÑ Ð²Ð¸Ð¿Ð°Ð´ÐºÑв, коли Ñ Ð¾Ñемо ÑÑвоÑиÑи ÑÑеÑаÑоÑ, ми викоÑиÑÑовÑÑмо генеÑаÑоÑи.
ÐÐ»Ñ Ð¿ÑоÑÑоÑи, опÑÑкаÑÑи деÑÐºÑ Ð²Ð°Ð¶Ð»Ð¸Ð²Ñ ÑеÑÑ, Ñе âÑÑнкÑÑÑ, ÑÐºÑ Ð³ÐµÐ½ÐµÑÑÑÑÑ (yield) знаÑеннÑâ. Ðони деÑалÑно опиÑÐ°Ð½Ñ Ð² ÑоздÑÐ»Ñ ÐенеÑаÑоÑи.
ÐенеÑаÑоÑи познаÑаÑÑÑÑÑ Ð¼ÑÑÐºÐ¾Ñ function* (звеÑнÑÑÑ ÑÐ²Ð°Ð³Ñ Ð½Ð° зÑÑоÑкÑ) Ñ Ð²Ð¸ÐºÐ¾ÑиÑÑовÑÑÑÑ yield, Ñоб генеÑÑваÑи знаÑеннÑ, ÑÐ¾Ð´Ñ Ð¼Ð¸ можемо викоÑиÑÑовÑваÑи for..of, Ñоб пеÑейÑи до ниÑ
.
Цей пÑиклад генеÑÑÑ Ð¿Ð¾ÑлÑдовнÑÑÑÑ Ð·Ð½Ð°ÑÐµÐ½Ñ Ð²Ñд start до end:
function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
yield i;
}
}
for(let value of generateSequence(1, 5)) {
alert(value); // 1, поÑÑм 2, поÑÑм 3, поÑÑм 4, поÑÑм 5
}
Як ми вже знаÑмо, Ñоб обâÑÐºÑ Ð¼Ñг пеÑебиÑаÑиÑÑ, ми Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñи до нÑого Symbol.iterator.
let range = {
from: 1,
to: 5,
[Symbol.iterator]() {
return <обâÑÐºÑ Ð· next, Ñоб зÑобиÑи дÑапазон ÑÑеÑабелÑним>
}
}
ÐвиÑÐ°Ð¹Ð½Ð¾Ñ Ð¿ÑакÑÐ¸ÐºÐ¾Ñ Ð´Ð»Ñ Symbol.iterator Ñ Ð¿Ð¾Ð²ÐµÑÐ½ÐµÐ½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑа. Як ви можеÑе баÑиÑи, Ñе ÑобиÑÑ ÐºÐ¾Ð´ коÑоÑÑим:
let range = {
from: 1,
to: 5,
*[Symbol.iterator]() { // ÑкоÑоÑÐµÐ½Ð½Ñ Ð´Ð»Ñ [Symbol.iterator]: function*()
for(let value = this.from; value <= this.to; value++) {
yield value;
}
}
};
for(let value of range) {
alert(value); // 1, поÑÑм 2, поÑÑм 3, поÑÑм 4, поÑÑм 5
}
ÐÑÐ´Ñ Ð»Ð°Ñка, пеÑеглÑнÑÑе ÑоздÑл ÐенеÑаÑоÑи, ÑкÑо вам поÑÑÑбно бÑлÑÑе деÑалей.
У звиÑайниÑ
генеÑаÑоÑаÑ
ми не можемо викоÑиÑÑовÑваÑи await. УÑÑ Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ Ð¼Ð°ÑÑÑ Ð½Ð°Ð´Ñ
одиÑи ÑинÑ
Ñонно, Ñк Ñого Ð²Ð¸Ð¼Ð°Ð³Ð°Ñ ÐºÐ¾Ð½ÑÑÑÑкÑÑÑ for..of.
Що, ÑкÑо ми Ñ Ð¾Ñемо генеÑÑваÑи знаÑÐµÐ½Ð½Ñ Ð°ÑÐ¸Ð½Ñ Ñонно? РмеÑÐµÐ¶ÐµÐ²Ð¸Ñ Ð·Ð°Ð¿Ð¸ÑÑв, напÑиклад.
ÐеÑейдÑмо до аÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ð¸Ñ Ð³ÐµÐ½ÐµÑаÑоÑÑв, Ñоб зÑобиÑи Ñе можливим.
ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи (наÑеÑÑÑ)
ÐÐ»Ñ Ð±ÑлÑÑоÑÑÑ Ð¿ÑакÑиÑÐ½Ð¸Ñ Ð·Ð°ÑÑоÑÑванÑ, коли ми Ñ Ð¾Ñемо ÑÑвоÑиÑи обâÑкÑ, Ñкий аÑÐ¸Ð½Ñ Ñонно генеÑÑÑ Ð¿Ð¾ÑлÑдовнÑÑÑÑ Ð·Ð½Ð°ÑенÑ, ми можемо викоÑиÑÑовÑваÑи аÑÐ¸Ð½Ñ Ñонний генеÑаÑоÑ.
СинÑакÑÐ¸Ñ Ð¿ÑоÑÑий: додайÑе async пеÑед function*. Це зÑобиÑÑ Ð³ÐµÐ½ÐµÑаÑÐ¾Ñ Ð°ÑинÑ
Ñонним.
РпоÑÑм ÑкоÑиÑÑайÑеÑÑ for await (...), Ñоб пеÑебÑаÑи його, напÑиклад:
async function* generateSequence(start, end) {
for (let i = start; i <= end; i++) {
// Ðго, можемо викоÑиÑÑовÑваÑи await!
await new Promise(resolve => setTimeout(resolve, 1000));
yield i;
}
}
(async () => {
let generator = generateSequence(1, 5);
for await (let value of generator) {
alert(value); // 1, поÑÑм 2, поÑÑм 3, поÑÑм 4, поÑÑм 5 (Ñз заÑÑÐ¸Ð¼ÐºÐ¾Ñ Ð¼Ñж ними)
}
})();
ÐÑкÑлÑки генеÑаÑÐ¾Ñ Ñ Ð°ÑинÑ
Ñонним, ми можемо викоÑиÑÑовÑваÑи вÑеÑÐµÐ´Ð¸Ð½Ñ Ð½Ñого await, пÑомÑÑи, виконÑваÑи меÑÐµÐ¶ÐµÐ²Ñ Ð·Ð°Ð¿Ð¸Ñи ÑоÑо.
ЯкÑо ви доÑвÑдÑений ÑиÑÐ°Ñ Ñ Ð¿Ð°Ð¼âÑÑаÑÑе деÑÐ°Ð»Ñ Ð¿Ñо генеÑаÑоÑи, Ñо знаÑÑе, Ñо ÑÐµÑ Ð½ÑÑно в Ð½Ð¸Ñ Ñ Ð²Ð½ÑÑÑÑÑÐ½Ñ ÑÑзниÑÑ.
ÐÐ»Ñ Ð°ÑинÑ
ÑонниÑ
генеÑаÑоÑÑв меÑод generator.next() Ñ Ð°ÑинÑ
Ñонним, вÑн повеÑÑÐ°Ñ Ð¿ÑомÑÑи.
У звиÑÐ°Ð¹Ð½Ð¾Ð¼Ñ Ð³ÐµÐ½ÐµÑаÑоÑÑ Ð¼Ð¸ викоÑиÑÑовÑÑмо result = generator.next(), Ñоб оÑÑимаÑи знаÑеннÑ. РаÑинÑ
ÑÐ¾Ð½Ð½Ð¾Ð¼Ñ Ð³ÐµÐ½ÐµÑаÑоÑÑ Ð¼Ð¸ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð´Ð¾Ð´Ð°Ñи await, напÑиклад:
result = await generator.next(); // result = {value: ..., done: true/false}
ÐÑÑ ÑÐ¾Ð¼Ñ Ð°ÑинÑ
ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи пÑаÑÑÑÑÑ Ð· for await...of.
ÐÑÐ¸Ð½Ñ Ñонно ÑÑеÑаÑÑйний range
ÐвиÑÐ°Ð¹Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи можна викоÑиÑÑовÑваÑи Ñк Symbol.iterator, Ñоб зÑобиÑи код ÑÑеÑаÑÑÑ ÐºÐ¾ÑоÑÑим.
ÐодÑбно до ÑÑого, аÑинÑ
ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи можна викоÑиÑÑовÑваÑи Ñк Symbol.asyncIterator Ð´Ð»Ñ ÑеалÑзаÑÑÑ Ð°ÑинÑ
ÑÐ¾Ð½Ð½Ð¾Ñ ÑÑеÑаÑÑÑ.
ÐапÑиклад, ми можемо змÑÑиÑи обâÑÐºÑ range генеÑÑваÑи знаÑÐµÐ½Ð½Ñ Ð°ÑинÑ
Ñонно, Ñаз за ÑекÑндÑ, замÑнивÑи ÑинÑ
Ñонний Symbol.iterator на аÑинÑ
Ñонний Symbol.asyncIterator:
let range = {
from: 1,
to: 5,
// Ñей ÑÑдок Ñакий Ñамий, Ñк [Symbol.asyncIterator]: async function*() {
async *[Symbol.asyncIterator]() {
for(let value = this.from; value <= this.to; value++) {
// Ñобимо паÑÐ·Ñ Ð¼Ñж знаÑеннÑми, ÑекаÑмо на ÑоÑÑ
await new Promise(resolve => setTimeout(resolve, 1000));
yield value;
}
}
};
(async () => {
for await (let value of range) {
alert(value); // 1, поÑÑм 2, поÑÑм 3, поÑÑм 4, поÑÑм 5
}
})();
Ð¢ÐµÐ¿ÐµÑ Ð·Ð½Ð°ÑÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ Ð¾Ð´ÑÑÑ Ñз заÑÑÐ¸Ð¼ÐºÐ¾Ñ Ð² 1 ÑекÑÐ½Ð´Ñ Ð¼Ñж ними.
ТеÑ
нÑÑно ми можемо додаÑи до обâÑкÑа Ñк Symbol.iterator, Ñак Ñ Symbol.asyncIterator, ÑÐ¾Ð¼Ñ Ð²Ñн може пеÑебиÑаÑиÑÑ Ñк ÑинÑ
Ñонно (for..of), Ñак Ñ Ð°ÑинÑ
Ñонно (for await..of).
Ðле на пÑакÑиÑÑ Ñе бÑло б дивно.
ÐÑиклад Ñз ÑеалÑÐ½Ð¾Ñ Ð¿ÑакÑики: поÑÑоÑÑÐ½ÐºÐ¾Ð²Ñ Ð´Ð°Ð½Ñ
Ðоки Ñо ми баÑили Ð±Ð°Ð·Ð¾Ð²Ñ Ð¿Ñиклади, Ñоб зÑозÑмÑÑи. Ð¢ÐµÐ¿ÐµÑ ÑозглÑнÑмо ÑеалÑний випадок викоÑиÑÑаннÑ.
ÐÑнÑÑ Ð±Ð°Ð³Ð°Ñо онлайн-ÑеÑвÑÑÑв, ÑÐºÑ Ð½Ð°Ð´Ð°ÑÑÑ Ð´Ð°Ð½Ñ Ð¿Ð¾ÑÑоÑÑнково. ÐапÑиклад, коли нам поÑÑÑбен ÑпиÑок коÑиÑÑÑваÑÑв, Ð·Ð°Ð¿Ð¸Ñ Ð¿Ð¾Ð²ÐµÑÑÐ°Ñ Ð¿Ð¾Ð¿ÐµÑеднÑо визнаÑÐµÐ½Ñ ÐºÑлÑкÑÑÑÑ (напÑиклад, 100 коÑиÑÑÑваÑÑв) â âÐ¾Ð´Ð½Ñ ÑÑоÑÑнкÑâ Ñа Ð½Ð°Ð´Ð°Ñ URL-адÑеÑÑ Ð½Ð°ÑÑÑÐ¿Ð½Ð¾Ñ ÑÑоÑÑнки.
Цей пÑÐ´Ñ Ñд дÑже поÑиÑений. Ðова йде не пÑо коÑиÑÑÑваÑÑв, а пÑо Ñо завгодно.
ÐапÑиклад, GitHub дозволÑÑ Ð½Ð°Ð¼ оÑÑимÑваÑи комÑÑи Ñаким же Ñином, ÑозбиÑими на ÑÑоÑÑнки:
- Ðи Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð·ÑобиÑи Ð·Ð°Ð¿Ð¸Ñ Ð·Ð° допомогоÑ
fetchÑ Ð²Ð¸Ð³Ð»ÑдÑhttps://api.github.com/repos/<repo>/commits. - У вÑдповÑÐ´Ñ Ð¿Ñийде JSON з 30 комÑÑами, а Ñакож з поÑиланнÑм на наÑÑÑÐ¿Ð½Ñ ÑÑоÑÑÐ½ÐºÑ Ð² заголовкÑ
Link. - Ð¢Ð¾Ð´Ñ Ð¼Ð¸ зможемо викоÑиÑÑаÑи Ñе поÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð´Ð»Ñ Ð½Ð°ÑÑÑпного запиÑÑ, Ñоб оÑÑимаÑи бÑлÑÑе комÑÑÑв Ñ Ñак далÑ.
ÐÐ»Ñ Ð½Ð°Ñого ÐºÐ¾Ð´Ñ Ð¼Ð¸ Ñ Ð¾ÑÑли б маÑи пÑоÑÑÑÑий ÑпоÑÑб оÑÑимаÑи комÑÑи.
СÑвоÑÑмо ÑÑнкÑÑÑ fetchCommits(repo), Ñка оÑÑимÑÑ ÐºÐ¾Ð¼ÑÑи Ð´Ð»Ñ Ð½Ð°Ñ, надÑилаÑÑи запиÑи, коли Ñе необÑ
Ñдно. РнеÑ
ай вона пÑклÑÑÑÑÑÑ Ð¿Ñо вÑÑ ÑеÑÑ Ñодо ÑозбиÑÑÑ Ð½Ð° ÑÑоÑÑнки. ÐÐ»Ñ Ð½Ð°Ñ Ñе бÑде пÑоÑÑа аÑинÑ
Ñонна ÑÑеÑаÑÑÑ for await..of.
ÐÑже, викоÑиÑÑÐ°Ð½Ð½Ñ Ð±Ñде Ñаким:
for await (let commit of fetchCommits("username/repository")) {
// опÑаÑÑÐ²Ð°Ð½Ð½Ñ ÐºÐ¾Ð¼ÑÑÑв
}
ÐÑÑ Ñака ÑÑнкÑÑÑ, ÑеалÑзована Ñк аÑÐ¸Ð½Ñ Ñонний генеÑаÑоÑ:
async function* fetchCommits(repo) {
let url = `https://api.github.com/repos/${repo}/commits`;
while (url) {
const response = await fetch(url, { // (1)
headers: {'User-Agent': 'Our script'}, // GitHub поÑÑебÑÑ Ð±ÑдÑ-Ñкий заголовок user-agent
});
const body = await response.json(); // (2) вÑдповÑÐ´Ñ Ñ ÑоÑмаÑÑ JSON (маÑив комÑÑÑв)
// (3) URL-адÑеÑа наÑÑÑÐ¿Ð½Ð¾Ñ ÑÑоÑÑнки знаÑ
одиÑÑÑÑ Ð² заголовкаÑ
, виÑÑгÑÑмо ÑÑ
let nextPage = response.headers.get('Link').match(/<(.*?)>; rel="next"/);
nextPage = nextPage?.[1];
url = nextPage;
for(let commit of body) { // (4) повеÑÑÐ°Ñ ÐºÐ¾Ð¼ÑÑи один за одним, поки ÑÑоÑÑнка не закÑнÑиÑÑÑÑ
yield commit;
}
}
}
ÐÑлÑÑе поÑÑÐ½ÐµÐ½Ñ Ð¿Ñо Ñе, Ñк Ñе пÑаÑÑÑ:
-
Ðи викоÑиÑÑовÑÑмо меÑод бÑаÑзеÑа fetch Ð´Ð»Ñ Ð·Ð°Ð²Ð°Ð½ÑÐ°Ð¶ÐµÐ½Ð½Ñ ÐºÐ¾Ð¼ÑÑÑв.
- ÐоÑаÑкова URL-адÑеÑа â
https://api.github.com/repos/<repo>/commits, а наÑÑÑпна ÑÑоÑÑнка бÑде в заголовкÑLinkвÑдповÑдÑ. - ÐеÑод
fetchдозволÑÑ Ð½Ð°Ð¼ надаÑи авÑоÑизаÑÑÑ Ñа ÑнÑÑ Ð·Ð°Ð³Ð¾Ð»Ð¾Ð²ÐºÐ¸, ÑкÑо Ñе Ð½ÐµÐ¾Ð±Ñ Ñдно â ÑÑÑ Ð´Ð»Ñ GitHub поÑÑÑбенUser-Agent.
- ÐоÑаÑкова URL-адÑеÑа â
-
ÐомÑÑи повеÑÑаÑÑÑÑÑ Ñ ÑоÑмаÑÑ JSON.
-
Ðи Ð¿Ð¾Ð²Ð¸Ð½Ð½Ñ Ð¾ÑÑимаÑи URL-адÑеÑÑ Ð½Ð°ÑÑÑÐ¿Ð½Ð¾Ñ ÑÑоÑÑнки Ñз заголовка
LinkвÑдповÑдÑ. ÐÑн Ð¼Ð°Ñ ÑпеÑÑалÑний ÑоÑмаÑ, ÑÐ¾Ð¼Ñ Ð¼Ð¸ викоÑиÑÑовÑÑмо Ð´Ð»Ñ ÑÑого ÑегÑлÑÑний виÑаз (пÑо ÑÑ ÑÑнкÑÑÑ Ð¼Ð¸ дÑзнаÑмоÑÑ Ð² РегÑлÑÑÐ½Ñ Ð²Ð¸Ñази).- URL-адÑеÑа наÑÑÑÐ¿Ð½Ð¾Ñ ÑÑоÑÑнки може виглÑдаÑи Ñак:
https://api.github.com/repositories/93253246/commits?page=2. Ðона ÑÑвоÑÑÑÑÑÑÑ Ñамим GitHub.
- URL-адÑеÑа наÑÑÑÐ¿Ð½Ð¾Ñ ÑÑоÑÑнки може виглÑдаÑи Ñак:
-
ÐоÑÑм ми видаÑмо оÑÑÐ¸Ð¼Ð°Ð½Ñ ÐºÐ¾Ð¼ÑÑи по ÑеÑзÑ, Ñ ÐºÐ¾Ð»Ð¸ вони закÑнÑаÑÑÑÑ, запÑÑÑиÑÑÑÑ Ð½Ð°ÑÑÑпна ÑÑеÑаÑÑÑ
while(url), ÑÑвоÑÑÑÑи Ñе один запиÑ.
ÐÑиклад викоÑиÑÑÐ°Ð½Ð½Ñ (показÑÑ Ð°Ð²ÑоÑÑв комÑÑÑв в конÑолÑ):
(async () => {
let count = 0;
for await (const commit of fetchCommits('javascript-tutorial/en.javascript.info')) {
console.log(commit.author.login);
if (++count == 100) { // зÑпинимоÑÑ Ð½Ð° 100 комÑÑаÑ
break;
}
}
})();
// ÐÑимÑÑка: ЯкÑо ви запÑÑкаÑÑе Ñе Ñ Ð·Ð¾Ð²Ð½ÑÑнÑй пÑÑоÑниÑÑ, вам поÑÑÑбно бÑде вÑÑавиÑи ÑÑди ÑÑнкÑÑÑ fetchCommits, опиÑÐ°Ð½Ñ Ð²Ð¸Ñе
Це Ñаме Ñе, Ñого ми Ñ Ð¾ÑÑли.
ÐнÑÑÑÑÑÐ½Ñ Ð¼ÐµÑ Ð°Ð½Ñка поÑÑоÑÑÐ½ÐºÐ¾Ð²Ð¸Ñ Ð·Ð°Ð¿Ð¸ÑÑв невидима ззовнÑ. ÐÐ»Ñ Ð½Ð°Ñ Ñе пÑоÑÑо аÑÐ¸Ð½Ñ Ñонний генеÑаÑоÑ, Ñкий повеÑÑÐ°Ñ ÐºÐ¾Ð¼ÑÑи.
ÐÑдÑÑмки
ÐвиÑÐ°Ð¹Ð½Ñ ÑÑеÑаÑоÑи Ñа генеÑаÑоÑи вÑдмÑнно пÑаÑÑÑÑÑ Ð· даними, ÑÑвоÑÐµÐ½Ð½Ñ ÑÐºÐ¸Ñ Ð½Ðµ поÑÑебÑÑ ÑаÑÑ.
Ðоли ми оÑÑкÑÑмо, Ñо Ð´Ð°Ð½Ñ Ð±ÑдÑÑÑ Ð½Ð°Ð´Ñ
одиÑи аÑинÑ
Ñонно Ñз заÑÑимками, можна викоÑиÑÑовÑваÑи ÑÑ
аÑинÑ
ÑÐ¾Ð½Ð½Ñ Ð°Ð½Ð°Ð»Ð¾Ð³Ð¸ Ñ for await..of замÑÑÑÑ for..of.
СинÑакÑиÑÐ½Ñ Ð²ÑдмÑнноÑÑÑ Ð¼Ñж аÑÐ¸Ð½Ñ Ñонними Ñа звиÑайними ÑÑеÑаÑоÑами:
| ÐÑеÑаÑоÑи | ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ ÑÑеÑаÑоÑи | |
|---|---|---|
| ÐеÑод Ð´Ð»Ñ Ð·Ð°Ð±ÐµÐ·Ð¿ÐµÑÐµÐ½Ð½Ñ ÑÑеÑаÑоÑа | Symbol.iterator |
Symbol.asyncIterator |
next() повеÑÑÐ°Ñ |
{value:â¦, done: true/false} |
Promise, Ñкий завеÑÑÑÑÑÑÑÑ Ð· {value:â¦, done: true/false} |
СинÑакÑиÑÐ½Ñ Ð²ÑдмÑнноÑÑÑ Ð¼Ñж аÑÐ¸Ð½Ñ Ñонними Ñа звиÑайними генеÑаÑоÑами:
| ÐенеÑаÑоÑи | ÐÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи | |
|---|---|---|
| ÐголоÑÐµÐ½Ð½Ñ | function* |
async function* |
next() повеÑÑÐ°Ñ |
{value:â¦, done: true/false} |
Promise, Ñкий завеÑÑÑÑÑÑÑÑ Ð· {value:â¦, done: true/false} |
У вебÑозÑобÑÑ Ð¼Ð¸ ÑаÑÑо зÑÑÑÑÑÑаÑмоÑÑ Ð· поÑоками Ð´Ð°Ð½Ð¸Ñ , коли вони Ð½Ð°Ð´Ñ Ð¾Ð´ÑÑÑ Ð¿Ð¾ ÑаÑÑÐ¸Ð½Ð°Ñ . ÐапÑиклад, заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð°Ð±Ð¾ виванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð²ÐµÐ»Ð¸ÐºÐ¾Ð³Ð¾ ÑайлÑ.
Ðи можемо викоÑиÑÑовÑваÑи аÑÐ¸Ð½Ñ ÑÐ¾Ð½Ð½Ñ Ð³ÐµÐ½ÐµÑаÑоÑи Ð´Ð»Ñ Ð¾Ð±Ñобки ÑÐ°ÐºÐ¸Ñ Ð´Ð°Ð½Ð¸Ñ . ÐаÑÑо Ñакож зазнаÑиÑи, Ñо в деÑÐºÐ¸Ñ ÑеÑедовиÑÐ°Ñ , напÑиклад Ñ Ð±ÑаÑзеÑÐ°Ñ , Ñ Ñакож ÑнÑий API пÑд Ð½Ð°Ð·Ð²Ð¾Ñ Streams (поÑоки), Ñкий Ð½Ð°Ð´Ð°Ñ ÑпеÑÑалÑÐ½Ñ ÑнÑеÑÑейÑи Ð´Ð»Ñ ÑобоÑи з Ñакими поÑоками, Ð´Ð»Ñ ÑÑанÑÑоÑмаÑÑÑ Ð´Ð°Ð½Ð¸Ñ Ñ Ð´Ð»Ñ ÑÑ Ð¿ÐµÑедаÑÑ Ð· одного поÑÐ¾ÐºÑ Ð² ÑнÑий (напÑиклад, заванÑÐ°Ð¶ÐµÐ½Ð½Ñ Ð· одного мÑÑÑÑ Ñ Ð½ÐµÐ³Ð°Ð¹Ð½Ðµ надÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð² ÑнÑе мÑÑÑе).
ÐоменÑаÑÑ
<code>, Ð´Ð»Ñ ÐºÑлÑÐºÐ¾Ñ ÑÑдкÑв â обгоÑнÑÑÑ ÑÑ Ñегом<pre>, Ð´Ð»Ñ Ð¿Ð¾Ð½Ð°Ð´ 10 ÑÑдкÑв â викоÑиÑÑовÑйÑе пÑÑоÑниÑÑ (plnkr, jsbin, codepenâ¦)