[resolve, then 슈도 코드]

const MyPromise = class {
  constructor(executor) {
    // new Promise( excutor )
    // 콜백으로 받아와서 resolve reject 넣어줘서 사용 하게끔 한다
    this.executor = executor;
    this.state = "pending";
    this.lastcalls = []; // [callback(this.value)] 가 담기게 된다.
    this.executor(this.resolve.bind(this));
  }

  resolve(value) {
    this.value = value;
    this.state = "resolved";
    this.lastcalls.forEach((lastcall) => {
      this.value = lastcall();
      // this.value는 처음 넣은 값부터 then 콜백의 리턴 값으로 계속 업데이트 된다
    });
    // resolve 함수 실행되면 되면 등록해놨던 then 콜백함수들 순서대로 다 실행
  }

  then(callback) {
    if (this.state === "pending") {
      this.lastcalls.push(() => callback(this.value)); // 콜백을 등록
      // value는 처음 넣은 값부터 then 콜백의 리턴 값으로 계속 업데이트 된다
    }
		return this; // 다음 체이닝 위해서 프로미스 다시 반환
  }
};
new MyPromise((resolve, reject) => {
	  setTimeout(() => {
	    resolve('첫번째 프로미스');
	  }, 1000);
	})
	  .then(value => { // this.value ( resolve 함수의 argument ) 
	    // callback 이 실행되지 않기 때문에 콘솔에 안찍힘
	    console.log(value); // 나중에 비동기 resolve가 실행된 후 그때 callback이 실행됨
	    return '두번째 프로미스';
	  })
	  .then(value => { // this.value ( 이전 then 콜백 의 return 값 )가 then의 콜백에 전달됨
	    console.log(value);
	  });

[완성 코드]

const MyPromise = class {
  constructor(executor) { // 프로미스 실행 함수, new Promise( 이 콜백함수 )
    this.state = 'pending'; // pending 상태에서 시작
    this.laterCalls = []; // 콜백들 모아놓은 배열
    this.decidePromiseByMethod.bind(this); // this 바인딩
    this.applyChangedState.bind(this); // this 바인딩

    try {
      executor(this.resolve.bind(this), this.reject.bind(this));
					// resolve, reject 콜백함수를 인자로 받아 상황 분기해서 실행
    } catch (error) {
      this.reject(error);
    }
  }

	// resolve 시 실행할 함수
	resolve(value) {
    this.applyChangedState(value, 'resolved');
  }

  applyChangedState(value, state) {
    if (!(this.state === 'pending')) return;
    if (value instanceof MyPromise) { // 프로미스 인자로 넣었을시 resolve( 여기에다가 )
      value.then(innerPromiseValue => {
        this.value = innerPromiseValue;
        this.status = state; // state resolve로 변경
        this.laterCalls.forEach(latercall => latercall());
      });
    } else { // 그냥 값 넣었을 경우
      this.value = value;
      this.state = state; // state resolve로 변경
      this.laterCalls.forEach(latercall => latercall());
			// then 에 등록한 콜백들 다 실행
    }
  }

	// then
	then(callback) {
    return this.decidePromiseByMethod('then', callback);
  }

  decidePromiseByMethod(method, callback) {
    const state = method === 'then' ? 'resolved' : 'rejected';
    if (this.state === state)
      return new MyPromise(resolve => resolve(callback(this.value)));
			// 콜백을 resolve 로 감싸야지 then 안에서 Promise 반환해도 대응가능

    if (this.state === 'pending') // pending 시 콜백에 등록하고 프로미스 리턴
      return new MyPromise(resolve => {
        this.laterCalls.push(() => resolve(callback(this.value)));
      });
    return this;
  }

  
  reject(value) {
    this.applyChangedState(value, 'rejected');
  }

  catch(callback) {
    return this.decidePromiseByMethod('catch', callback);
  }
};
module.exports = MyPromise;

참고


Custom Promise 구현으로 프로미스 파혜치기 - p-iknow's devlog