- Iterator
- Generator
- Promise
- Async-Await
κ·Έμ μ κ°μ₯ λ¨Όμ for-of
μ λν΄μ μμ보μ
μ°λ¦¬κ° νν μ¬μ©νκ³ λ§μ΄ μ¬μ©νλ for
λ¬Έμ΄ μλ€. κ·Έλ¬λ μ΄λμλΆν° μ΄λκΉμ§ μ§μ μ νλκ²μ΄ μλ μ 체λ₯Ό μννλ€κ³ νλ©΄ for-in
μ΄λ foreach
λ₯Ό μ¬μ©νλ€.
for-in
μ κ°κ°μ key
λ₯Ό λ°μμμ κ·Έ ν€λ₯Ό κ°μ§κ³ value
λ₯Ό κ°μ ΈμμΌνλ©° foreach
λ μ€κ°μ λμ¬ μ μλ€λ λ¨μ μ κ°μ§κ³ μλ€.
μ΄λ¬νμ¬ μκΈ΄κ²μ΄ for-of
μ΄λ€.
ECMA2015μ μλ‘μ΄ λ¬Έλ²μΌλ‘ μΆκ°κ° λμμΌλ©° μ΄κ²μ λ°°μ΄μ λ¬Όλ‘ object
κΉμ§ μνκ° κ°λ₯νλ€.(λ¬Όλ‘ keyκ° μμ΄μΌ κ°λ₯)
for-ofλ¬Έμ μ΄κ±°κ° κ°λ₯ν κ°μ²΄λΌλ©΄ 무μμ΄λ μνκ° κ°λ₯νλ€.
κ·Έλ λ€λ©΄ μ΄κ±°κ°λ₯ν κ°μ²΄λ 무μμΈκ°?
π λ°°μ΄(Array)λ λ¬Όλ‘ , TypedArray, λ¬Έμμ΄(String), Map, Set, DOM Collection λ±μ λ§νλ€.
/* array */
let iterable = [10, 20, 30];
for (let value of iterable) {
console.log(value); // 10 20 30
}
/* string */
let iterable = "boo";
for (let value of iterable) {
console.log(value); // "b" "o" "o"
}
/* Typed Array */
let iterable = new Uint8Array([0x00, 0xff]);
for (let value of iterable) {
console.log(value); // 0 255
}
/* Map */
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let entry of iterable) {
console.log(entry); // [a, 1] [b, 2] [c, 3]
}
for (let [key, value] of iterable) {
console.log(value); // 1 2 3
}
/* Set */
let iterable = new Set([1, 1, 2, 2, 3, 3]);
for (let value of iterable) {
console.log(value); // 1 2 3
}
/* DOM Collection */
let articleParagraphs = document.querySelectorAll("article > p");
for (let paragraph of articleParagraphs) {
paragraph.classList.add("read");
}
μ΄λ»κ² μνλ₯Ό ν μ μλ κ²μΌκΉ β
π iterator
λλΆμ΄λ€.
Collection
λ€μ λ΄λΆμ μΌλ‘ Iterable Protocol
μ ꡬννλ€.
μ΄λ€κ°μ²΄κ° μνκ° λκΈ° μν΄μλ iteration
λμμ λν΄ μ μκ° λμ΄ μμ΄μΌ νλ€.
Iterable Protocol
μ μνλ©΄ Iterator
λ next()
ν¨μλ₯Ό ꡬνν΄μΌνκ³ μ΄ ν¨μλ κ²°κ³Όκ°μΌλ‘ {value: value, doen: boolean}
κ°μ κ°μ²΄λ₯Ό λ°νν΄μΌ νλ€κ³ νλ€.
Ex) ꡬνν΄λ³΄κΈ°
function makeRangeIterator(start = 0, end = Infinity, step = 1) {
var nextIndex = start;
var n = 0;
var rangeIterator = {
next: function() {
var result;
if (nextIndex < end) {
result = { value: nextIndex, done: false }
} else if (nextIndex == end) {
result = { value: n, done: true }
} else {
result = { done: true };
nextIndex += step;
n++;
return result;
}
};
return rangeIterator;
}
// run iterator
const it = makeRangeIterator(1, 4);
let result = it.next();// μ²μ νλ² μ€ν
while (!result.done) {
console.log(result.value); // 1 2 3
result = it.next();
}
ECMA2015
μμλ Iterator protocol
μ μ΄μ©νμ¬ μ΄κ±°κ°λ₯ν κ°μ²΄λ₯Ό λ§λ€ μ μλ€.
[Symbol.iterator]()
μ next()
λ₯Ό μ΄μ©νλ©΄ μ½κ² μ μν μ μλ€.
for-of
λ [Symbol.iterator]()
λ₯Ό νΈμΆνμ¬ λ°λ³΅μ μ€ννκ² λλ€.
μμ π
const iterable = {
[Symbol.iterator]() {
return {
i: 0,
next() {
if (this.i < 3) {
return { value: this.i++, done: false };
}
return { value: undefined, done: true };
}
};
}
};
for (var value of iterable) {
console.log(value); // 0 1 2
}
Iterator
μ λΉμ·ν μ΄λ
μμ μΌμ’
μ **μ½λ£¨ν΄(Co-Routine)**μΈλ°, λ€λ₯Έ μΈμ΄μμλ 곧 μ μ¬μ©νλ κ°λ
μ΄λ€.
μ½λ£¨ν΄(Co-Routine) : μ΄λ μμ μ νλ€κ° μ€κ°μ λ©μΆκ³ λ©μΆλΆλΆλΆν° λ€μ μμμ΄ κ°λ₯ν
Generator
λ ν¨μ μ€νλμ€μ μ μ λ©μ·λ€κ° λ€μ μ€νν μ μλ λ
νΉν ν¨μμ΄λ€. Generator
λ function*
ν€μλλ₯Ό μ¬μ©ν΄μ μμ±νλ©°,
Generator
λ₯Ό νΈμΆνλ©΄ μ€νλλ κ²μ΄ μλλΌ Iterator
κ°μ²΄κ° λ°νλλ€.
λ°λΌμ Iterator
μμ ꡬνν next()
ν¨μλ₯Ό νΈμΆνλ©΄ Generator
κ° μ€νλλ©΄μ yield
λ₯Ό λ§λ λκΉμ§ μ€νλκ³ , μ΄λ 컨ν
μ€νΈλ μ μ₯λ μνλ‘ λ¨μ μκ² λλ€.
μμ π
function* idMaker(){
var index = 0;
while(index < 3)
yield index++;
}
const gen = idMaker(); // iteratorκ°μ²΄κ° λ°ν
console.log(get.next());
console.log(get.next());
console.log(get.next());
Generator
λ₯Ό μ¬μ©νλ©΄ Iterable Protocol
μ ꡬννλ κ²λ³΄λ€ μ’ λ μ½κ² Iterator
λ₯Ό μ¬μ©ν μ μλ€.
Generator
μ μ§λ©΄λͺ©μ λΉλκΈ° νλ‘κ·Έλλ°μμ λ³Ό μ μλ€. ν¨μκ° μ€ν λμ€μ λ©μΆλ€λ. μΈμ μλ΅μ΄ μ¬μ§ μ μ μκΈ° λλ¬Έμ, callback
μ λ±λ‘νλ λΉλκΈ° νλ‘κ·Έλλ°μ μμ©νλ©΄ callback hell
μ νμΆν μ μμ§ μμκΉ?
generator
λ μμ ES5
μ€νμ΄ μλλ€ ES6
μ΄λ€.
κ·Έλ λ€λ©΄ Generator
λ λ μ΄λ»κ² ꡬνμ΄ λμ΄μλ κ²μΈκ°?
// ES6
function* foo(){
yield bar();
}
// ES5 Compiled
"use strict";
var _marked = /*#__PURE__*/ regeneratorRuntime.mark(foo);
function foo() {
return regeneratorRuntime.wrap(
function foo$(_context) {
while (1) {
switch ((_context.prev = _context.next)) {
case 0:
_context.next = 2;
return bar();
case 2:
case "end":
return _context.stop();
}
}
},
_marked, this
);
}
Genrator
λ κ²°κ΅ iterable Protocel
λ₯Ό ꡬννλ κ°μ²΄μ΄λ€. κ·Έλ¬λ νλ‘ν μ½κ³Ό κ΄λ ¨λ μ΄λκ²λ 보μ΄μ§ μλλ€.
λμ regeneratorRuntime
μ΄κ²μ΄ 보μΈλ€.
babel
μμλ regeneratorRuntime
λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©ν΄μ ꡬνμ νλ€.
μ½λμ μμ¬λ₯Ό λ°λΌκ°λ€ 보면 facebook/regenerator repository
μ λλ¬νκ² λλ€.
https://github.com/facebook/regenerator/blob/master/packages/regenerator-runtime/runtime.js
μ΄ λΌμ΄λΈλ¬λ¦¬λ 2013λ
Node.js v0.11.2
μμ generator syntax
λ₯Ό μ§μνκΈ° μν΄ λ§λ€μ΄ μ‘μΌλ©°, Babel
μμλ μ΄ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νμ¬ generator
λ₯Ό ꡬννκ³ μλ€.
μ€μ μ½λλ₯Ό λ€μ¬λ€λ³΄λ©΄ Symbol
κ³Ό Iterator
λ₯Ό μ΄μ©ν΄μ Iterable Protocol
μ ꡬννκ³ μλ€.
μ΄μ λ³Έλ‘ μΌλ‘ λμμμ Async-await
μ μ΄λ»κ² ꡬνμ΄ λμλκ°??
Async-await
λ ECMA-262
μμ μ΄μμΌλ‘ μ²μ λ±μ₯νμΌλ©°, ECMAScript 2017
μμ νμ€μΌλ‘ μ μλμλ€.(ES8
μμ νμ€μ΄ λμλ€.)
λ¨Όμ Babel
μμ Async-await
λ₯Ό λλ¦¬κ² λλ©΄ ES5
λ²μ μΌλ‘ λμ¨λ€. κ·Έλ λ€λ©΄ ES5
λ‘ κ΅¬νμ΄ κ°λ₯νλ€λ κ²μ΄λ€. μ€μ λ‘ Babel
λ‘ λλ¦¬κ² λλ©΄ μλμ κ°μ κ²°κ³Όκ° λμ¨λ€.
// ES7
async function foo() {
await bar();
}
// ES5 complied
let foo = (() => {
var _ref = _asyncToGenerator(function*() {
yield bar();
});
return function foo() {
return _ref.apply(this, arguments);
};
})();
function _asyncToGenerator(fn) {
return function() {
var gen = fn.apply(this, arguments);
return new Promise(function(resolve, reject) {
function step(key, arg) {
try {
var info = gen[key](arg);
var value = info.value;
} catch (error) {
reject(error);
return;
}
if (info.done) {
resolve(value);
} else {
return Promise.resolve(value).then(
function(value) {
step("next", value);
},
function(err) {
step("throw", err);
}
);
}
}
return step("next");
});
};
}
μμ μ»΄νμΌλ¨ ꡬ문μ λ³΄κ² λλ©΄ async keyword
λ₯Ό generator
λ‘ λ°κΎΈκ³ await keyword
λ yield
λ‘ λ°κΎΈμλ€.
Generator
λ yield
λ₯Ό λ§λ λκΉμ§ μ€νλλ€. μ΄λ Context
λ μ μ₯λ μνλ‘ λ¨μμκ² λλ€.
μ¦ Generator
λ‘ λΉλκΈ° λ‘μ§μ΄ λλ λλ§λ€ μ μ ν next()
λ₯Ό μ μ νκ² νΈμΆν΄μ£Όλ©΄ Async-Await
ν¨μκ° λ§λ€μ΄ μ§λ κ²μ΄λ€.
κ·Έλ¬λ bar()
ν¨μμ μμ
μ΄ μ’
λ£λλ μμ μ bar()
ν¨μλ°μ λͺ¨λ₯Έλ€. κ·Έλ λ€κ³ next()
λ₯Ό bar()
ν¨μ λ΄μμ μ§μ μ€ννκ² λλ€λ©΄ μμ‘΄μ±μ΄ μκΈ°κ² λλ€.
κ·Έλ λ€λ©΄ μ΄λ»κ² μμ‘΄μ±μ λΆλ¦¬ ν μ μμκΉ?
ββ Promise
ββ
Babel
μ promise
μ μ¬κ·ν¨μ
λ₯Ό μ΄μ©νμ¬ next()
λ₯Ό λμ νΈμΆν΄μ£Όλ ν¨μλ₯Ό λ§λλλ°, κ·Έκ² λ°λ‘ _asyncToGenerator
μ΄λ€.
fn.apply
λ₯Ό μ€ννμ¬ μΈμλ‘ λμ΄μ¨ Generator
λ₯Ό μ€ννμ¬ iterator
κ°μ²΄λ₯Ό ν΄λ‘μ λ‘ μ μ₯ν΄λλ€. λλ¨Έμ§λ ν΄λ‘μ μ μ μ₯ν iterator
λ₯Ό μ€νμν€κ³ , λ°νλ promise
κ°μ²΄λ₯Ό μ¬κ·ν¨μλ₯Ό ν ν΄ λ°λ³΅μ€ν
μ 리νμλ©΄ Generator
λ λΉλκΈ°μ ν¨ν΄μ yield
λ₯Ό ν΅ν΄ λκΈ°μ μΈ βλͺ¨μ΅"μΌλ‘ λ°κΎΈμ΄μ£Όκ³ , Promise
λ Generator
λ‘ λ§λ iterator
λ₯Ό λ°λ³΅ν΄μ μ€νν΄μ£Όλ μν μ νλ€. await keyword
μ μ¬μ©νλ ν¨μκ° νμ promise
λ₯Ό λ°νν΄μΌνλ μ΄μ κ° μ¬κΈ°μ μλ€.
Promise => νλ‘λ―Έμ€λ μλ°μ€ν¬λ¦½νΈ λΉλκΈ° μ²λ¦¬μ μ¬μ©λλ κ°μ²΄μ λλ€. μ¬κΈ°μ μλ°μ€ν¬λ¦½νΈμ λΉλκΈ° μ²λ¦¬λ βνΉμ μ½λμ μ€νμ΄ μλ£λ λκΉμ§ κΈ°λ€λ¦¬μ§ μκ³ λ€μ μ½λλ₯Ό λ¨Όμ μννλ μλ°μ€ν¬λ¦½νΈμ νΉμ±βμ μλ―Έν©λλ€
π Promise
λ‘λ§ κ΅¬νν κ²½μ°
const makeRequest = () => {
return getJSON()
.then(data => {
if (data.needsAnotherRequest) {
return makeAnotherRequest(data)
.then(moreData => {
console.log(moreData)
return moreData
})
} else {
console.log(data)
return data
}
})
}
π async-await
λ‘ κ΅¬νν κ²½μ°
const makeRequest = async () => {
const data = await getJSON()
if (data.needsAnotherRequest) {
const moreData = await makeAnotherRequest(data);
console.log(moreData)
return moreData
} else {
console.log(data)
return data
}
}