다시, 자바스크립트 (7) - 프로미스 + 제너레이터 + 프록시

Junho Yun·2023년 3월 25일
0
post-thumbnail

프로미스

동기 / 비동기

자바스크립트는 동기적으로 작동됩니다. 즉, 각 코드 블록이 이전 블록 이후에 실행 됩니다.

const data = fetch(`api-url`);
console.log("완료");
cnosole.log(data);

fetch가 비동기로 동작합니다. fetch가 완료되지 않아 console.log(data)에 undefined가 나오게 됩니다. 이러한 일들을 비동기 처리해준다고 말하며 동기적으로 작동시키도록 코드를 바꿔보겠습니다.

콜백 지옥

비동기 코드를 동기식으로 작동하게 하는 방법 중 가장 기본적인 방법이 callback을 이용하는 방법입니다.
하지만 이를 난발할 경우 콜백 지옥이라는 말이 나오는 상황이 발생하게 됩니다.

function doSomething(callback) {
  setTimeout(function() {
    console.log("First thing done");
    callback();
  }, 1000);
}

function doSomethingElse(callback) {
  setTimeout(function() {
    console.log("Second thing done");
    callback();
  }, 1000);
}

function doYetAnotherThing(callback) {
  setTimeout(function() {
    console.log("Third thing done");
    callback();
  }, 1000);
}

doSomething(function() {
  doSomethingElse(function() {
    doYetAnotherThing(function() {
      console.log("All things done");
    });
  });
});

프로미스

프로미스는 비동기 작업의 최종 성공 또는 실패를 나타내는 객체이다.

지옥에서 벗어나는 방법이 바로 프로미스 입니다.

프로미스의 상태는 3가지가 있습니다.

  • 대기(pending): 이행하지도, 거부하지도 않은 초기 상태.
  • 이행(fulfilled): 연산이 성공적으로 완료됨.
  • 거부(rejected): 연산이 실패함.

작업의 최종 결과를 처리하는 데 사용할 수 있는 두 가지 방법이 있습니다.

  • then() - 이 메서드는 Promise가 이행될 때 호출되며 Promise가 이행될 때 호출되는 성공 콜백 함수와 선택적 오류 콜백 함수의 두 가지 인수를 사용합니다.
  • catch() - 이 메서드는 Promise가 거부될 때 호출되며 오류 콜백 함수인 단일 인수를 사용합니다.
// 프로미스 생성
const myPromise = new Promise((resolve, reject)=> {
	resolve("the value we get from the promise");
});

// 프로미스 호출 
myPromise.then(
	data => {
    	console.log(data);
    });
// the value we get from the promise

프로미스 체이닝

프로미스의 성공 또는 실패 여부와 무관하게 이전 프로미스에서 반환된 것을 계속 프로미스의 기반으로 사용하여 프로미스를 체이닝 할 수 있습ㄴ디ㅏ.

원하는 만큼 프로미스를 연결 할 수 있고, 이는 콜백지옥보다 간결하고 가독성 좋은 코드를 만들게 해줍니다.

firstAsyncOperation()
  .then(secondAsyncOperation)
  .then(thirdAsyncOperation)
  .then(fourthAsyncOperation)
  .then(function() {
    console.log("All operations complete!");
  })
  .catch(function(error) {
    console.log("An error occurred: " + error.message);
  });

프로미스 .resolve(), .reject()

Promise.resolve() 와 Promise.reject()는 각각 자동으로 성공 혹은 실패하는 프로미스를 생성합니다.

let myPromise = Promise.resolve("hello world");
myPromise.then(function(value) {
  console.log(value); // outputs "hello world"
});

let myPromise = Promise.reject(new Error("Something went wrong"));
myPromise.catch(function(error) {
  console.log(error.message); // outputs "Something went wrong"
});

프로미스 .all(), .race()

Promise.all()은 모든 프로미스가 성공할 경우에만 성공하는 하나의 프로미스를 반환합니다.
이와는 다르게, Promise.race()는 이터러블에 포함된 프로미스들 중 가장 먼저 성공 또는 실패한 결과를 반환합니다.

let promise1 = Promise.resolve(1);
let promise2 = Promise.resolve(2);
let promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
  .then(function(values) {
    console.log(values); // outputs [1, 2, 3]
  })
  .catch(function(error) {
    console.log(error.message);
  });
let promise1 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 1000, 'one');
});

let promise2 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 2000, 'two');
});

Promise.race([promise1, promise2])
  .then(function(value) {
    console.log(value); // outputs "one"
  })
  .catch(function(error) {
    console.log(error.message);
  });

제너레이터

제너레이터 함수는 원하는 만큼 코드 실행을 시작하거나 중지할 수 있는 함수 입니다.

제너레이터를 사용한 배열 반복

function* generateArray(array) {
  for(let i = 0; i < array.length; i++) {
    yield array[i];
  }
}

const arr = [1, 2, 3, 4, 5];
const gen = generateArray(arr);

console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
console.log(gen.next().value); // 4
console.log(gen.next().value); // 5

.return()을 활용한 제너레이터 종료

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = generateSequence();

console.log(gen.next().value); // 1
console.log(gen.return("Terminating the sequence").value); // Terminating the sequence
console.log(gen.next().value); // undefined

.throw()로 오류 잡기

function* generateError() {
  try {
    yield 1;
    yield 2;
    yield 3;
  } catch(error) {
    console.log(error.message);
  }
}

const gen = generateError();

console.log(gen.next().value); // 1
console.log(gen.throw(new Error("Error occurred")));// Error occurred

제너레이터와 프로미스 함께 사용하기

function* generateSequence() {
  yield 1;
  yield 2;
  yield 3;
}

const gen = generateSequence();

const promise = new Promise((resolve, reject) => {
  const intervalId = setInterval(() => {
    const next = gen.next();
    if(next.done) {
      clearInterval(intervalId);
      resolve();
    } else {
      console.log(next.value);
    }
  }, 1000);
});

promise.then(() => {
  console.log("Sequence complete");
});

프록시

프록시 생성

JavaScript에서 프록시는 대상 개체의 동작을 사용자 지정하고 제어할 수 있도록 다른 개체에서 수행되는 작업을 가로채는 개체입니다.

const proxy = new Proxy(target, handler);

프록시 활용

const obj = {
  name: 'John',
  age: 30
};

const proxy = new Proxy(obj, {
  get(target, property) {
    console.log(`Getting ${property} value`);
    return target[property];
  },

  set(target, property, value) {
    console.log(`Setting ${property} value to ${value}`);
    target[property] = value;
  },

  deleteProperty(target, property) {
    console.log(`Deleting ${property}`);
    delete target[property];
  }
});

console.log(proxy.name); // Getting name value, John
proxy.age = 35; // Setting age value to 35
delete proxy.age; // Deleting age
profile
의미 없는 코드는 없다.

0개의 댓글