티스토리 뷰
728x90
Iteration Protocol
- ES6에 도입되어 데이터 컬렉션을 순회하기 위한 규칙
- Iteration Protocol을 준수하면 for.. of, Spread 문법을 사용할 수 있음.
- Iteration Protocol = Iterable Protocol + Iterator Protocol
const array = [1, 2, 3];
for (const value of array) {
console.log(value);
}
console.log(...array);
Iterable Protocol
Symbol.iterator 메소드를 구현한 객체를 의미한다. (나 순회 할수 있어! 라고 알려주는 척도)
const array = [1, 2, 3];
// iterator가 배열에 존재하는지 여부
console.log(Symbol.iterator in array); // true
for (const value of array) {
console.log(value); // OK
}
const object = { key: 'value' };
// iterator가 일반 객체에 존재하는지 여부
console.log(Symbol.iterator in object); // false
// ERROR
for (const value of object) {
console.log(value); // FAIL
}
위와 같이 배열의 경우 Symbol.iterator 메소드를 가지고 있기 때문에 순회가능하지만 object의 경우는 불가능함.
Iterator Protocol
Iterator는 Iterable 객체에서 반환되는 객체로 next를 호출하여 순회가능하다.
next호출시 value(값)과 done(순회 끝 여부)를 반환한다.
const array = [1, 2, 3];
// 이터러블 객체인지 확인
console.log(Symbol.iterator in array); // true
// 이터레이터 객체 할당
const it = array[Symbol.iterator]();
console.log(it.next()); // { value: 1, done: false }
console.log(it.next()); // { value: 2, done: false }
console.log(it.next()); // { value: 3, done: false }
console.log(it.next()); // { value: undefined, done: true }
for..of / spread 연산자
for문, spread연산자의 경우 iterator 객체에서 done이 true가 나오기 전까지 next를 호출해 value를 반환하는 형식을 취하고있다.
const array = [1, 2, 3];
for (const value of array) {
console.log(value);
}
console.log(...array);
Generator 함수
- ES6에서 도입된 제너레이터(Generator) 함수는 이터러블(Iterable)을 생성하는 함수이다.
- 제너레이터 함수는 비동기 처리에 유용하게 사용된다.
Generator함수는 일반 함수와 다르게 한번에 실행하지 않고 중지했다가 필요한 시점에 실행 할 수 있다.
// 제너레이터 함수는 일반 함수와 같이 함수의 코드 블록을 한 번에 실행하지 않고
// 함수 코드 블록의 실행을 일시 중지했다가 필요한 시점에 재시작할 수 있는 특수한 함수
function* counter() {
console.log('첫번째 호출');
yield 1; // 첫번째 호출 시에 이 지점까지 실행된다.
console.log('두번째 호출');
yield 2; // 두번째 호출 시에 이 지점까지 실행된다.
console.log('세번째 호출'); // 세번째 호출 시에 이 지점까지 실행된다.
}
// 함수를 실행한것이 아닌 제너레이터를 생성한것.
const counterGenerator = counter();
// Iterable Protocol 준수
console.log(Symbol.iterator in counterGenerator); // true
console.log(counterGenerator.next()); // 첫번째 호출 {value: 1, done: false}
console.log(counterGenerator.next()); // 두번째 호출 {value: 2, done: false}
console.log(counterGenerator.next()); // 세번째 호출 {value: undefined, done: true}
next() 메소드를 호출하면 처음 만나는 yield 문까지 실행되고 일시 중단된다. 또 다시 next() 메소드를 호출하면 중단된 위치에서 다시 실행이 시작하여 다음 만나는 yield 문까지 실행되고 또 다시 일시 중단된다.
next 함수 파라미터 전달
function* gen() {
let res;
res = yield 'start'; // 'start'
console.log(res); // res: 1 ⟸ 두번째 next 호출 시 전달한 데이터
res = yield res;
console.log(res); // res: 2 ⟸ 세번째 next 호출 시 전달한 데이터
res = yield res;
console.log(res); // res: 3 ⟸ 네번째 next 호출 시 전달한 데이터
return res;
}
const generatorObj = gen();
console.log(generatorObj.next()); // 제너레이터 함수 시작
console.log(generatorObj.next(1)); // 제너레이터 객체에 1 전달
console.log(generatorObj.next(2)); // 제너레이터 객체에 2 전달
console.log(generatorObj.next(3)); // 제너레이터 객체에 3 전달
/*
{ value:'start', done: false }
{ value: 1, done: false }
{ value: 2, done: false }
{ value: 3, done: true }
*/
Generator 함수를 이용한 비동기 처리
const fetch = require('node-fetch');
// 외부 api를 사용한다.
function getUser(generatorObject, username) {
fetch(`https://api.github.com/users/${username}`)
.then(res => res.json())
.then(user => {
// user 이름을 줄테니까 다음을 실행시켜!
generatorObject.next(user.name)
});
}
let main;
// 비동기 함수가 포함되어있는 메인함수
function* mainFunction() {
let user;
// getUser를 실행하고 멈춰있어!
user = yield getUser(main, 'jessie');
console.log('1user - ', user);
user = yield getUser(main, 'kevin');
console.log('2user - ', user);
user = yield getUser(main, 'albert');
console.log('3user - ', user);
}
// iterator 함수 반환
main = mainFunction();
// main 함수 실행
main.next();
Async/Await을 이용한 비동기 처리
위와 기능은 같지만 한결 보기 편함.
const fetch = require('node-fetch');
(async function () {
let username, res, user;
username = 'jessie';
res = await fetch(`https://api.github.com/users/${username}`);
user = await res.json();
console.log('res.name - ', user.name);
username = 'kevin';
res = await fetch(`https://api.github.com/users/${username}`);
user = await res.json();
console.log('res.name - ', user.name);
username = 'albert';
res = await fetch(`https://api.github.com/users/${username}`);
user = await res.json();
console.log('res.name - ', user.name);
})();
출처
poiemaweb.com/es6-iteration-for-of
728x90
'개발 언어 > NodeJS' 카테고리의 다른 글
Deno (0) | 2020.06.15 |
---|---|
NodeJS - WebRTC (0) | 2020.02.28 |
NodeJS - Socket IO (0) | 2020.02.28 |
비동기 프로그래밍 (0) | 2020.01.11 |
자바스크립트 - 프로토타입 상속 (0) | 2019.12.03 |
댓글