손 으로 쓴 Promise. - 기본 적 인 Promise 를 실현 합 니 다.
손 으로 쓴 Promise. - 기본 적 인 Promise 를 실현 합 니 다. 수기 Promise - 실례 방법 catch, finally 필기 Promise - 정적 방법 all, any, resolve, reject, race
Promise 를 아 는 것 부터...
/* */
function fetchData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('willem');
}, 1000);
});
}
fetchData().then((data) => {
// after 1000ms
console.log(data); // willem
return 'wei';
}, (err) => {}).then((data2) => {
console.log(data2); // wei
});
위의 예 는 가장 흔히 볼 수 있 는 용법 이 라 고 할 수 있다. 사용 할 때 이상 을 처리 하여
catch
방법 을 대체 하 는 두 번 째 매개 변 수 를 더 많이 사용 할 수 있 지만 then
도 하나의 catch
문법 사탕 에 불과 하 다.그 중에서 우 리 는 몇 가지 문장 으로 Promise 를 묘사 할 수 있다.
단판 Promise
1. promise 는 하나의 클래스 입 니 다. 구조 함수 가 하나의 함 수 를 받 아들 이 고 함수 의 두 매개 변수 도 모두 함수 입 니 다.
첫 번 째 는 쉬 워 요.
// Promise
class WPromise {
constructor(executor) {
// this this ,this ,
executor(this._resolve.bind(this), this._reject.bind(this));
}
_resolve() {}
_reject() {}
}
2. 들 어 오 는 함수 에서 resolve 를 실행 하면 성공 을 표시 하고 reject 를 실행 하면 실 패 를 표시 하 며 들 어 오 는 값 은 then 방법의 리 셋 함수 에 전 달 됩 니 다.
성공, 실패, 이것 은 하나의 상 태 를 사용 하여 표 시 를 할 것 이 라 고 생각 하기 쉬 우 며, 실제로 Promise 는 이렇게 한다.Promise 에서 현재 상 태 를 표시 하기 위해
then
를 사 용 했 습 니 다.pending、fulfilled、rejected
초기 상 태 는 성공 도 실패 상태 도 아니다.resolve 나 reject 가 업데이트 상 태 를 호출 할 때 까지 기 다 립 니 다.pending
는 조작 이 성공 적 으로 완성 되 었 다 는 것 을 의미한다.fulfilled
는 조작 실 패 를 의미한다.주의해 야 할 것 은 이 세 가지 상태 사이 에 두 개의 변환 관계 만 존재 한 다 는 것 이다.
rejected
에서 pending
로 전환 되 며, resolve 방법 으로 만 전환 이 완료 된다 fulfilled
에서 pending
로 전환 되 며, reject 방법 으로 만 전환 이 완료 된다 들 어 오 는 값 은
rejected
의 반전 함수 에 전 달 됩 니 다. 어떻게 전달 합 니까?분명히 우 리 는 resolve 와 reject 의 값 을 저장 할 것 이다.위의 상태 와 값 을 Promise 에 추가 합 니 다.
class WPromise {
static pending = 'pending';
static fulfilled = 'fulfilled';
static rejected = 'rejected';
constructor(executor) {
this.status = WPromise.pending; // pending
this.value = undefined; // this._resolve
this.reason = undefined; // this._reject
executor(this._resolve.bind(this), this._reject.bind(this));
}
_resolve(value) {
this.value = value;
this.status = WPromise.fulfilled; //
}
_reject(reason) {
this.reason = reason;
this.status = WPromise.rejected; //
}
}
3. Promise 는 then 이라는 방법 이 있 습 니 다. 이 방법 은 두 개의 매개 변수 가 있 습 니 다. 첫 번 째 매개 변 수 는 성공 한 후에 실 행 된 리 셋 함수 이 고 두 번 째 매개 변 수 는 실패 한 후에 실 행 된 리 셋 함수 입 니 다.then 방법 은 resolve 나 reject 가 실 행 된 후에 야 실 행 됩 니 다. then 방법 중의 값 은 resolve 나 reject 에 전 달 된 매개 변수 입 니 다.
이 말 은 좀 길다. 주의해 야 할 것 은 이 말
then
이다. 우 리 는 Promise 가 비동기 라 는 것 을 알 고 있다. 즉, then resolve reject
들 어 오 는 함 수 는 바로 실행 할 수 없고 저장 해 야 하 며 resolve 함수 가 실 행 된 후에 야 꺼 내 서 실행 해 야 한다.다시 말 하면 이 과정 은
then
과 유사 하 다. 우 리 는 then 을 사용 하여 사건 을 등록 합 니 다. 그러면 언제 이 사건 들 이 실행 되 는 지 알려 줍 니까?정 답 은 resolve 방법 이 실행 되 거나 reject 방법 이 실 행 될 때 입 니 다.ok, 우리 의 코드 를 계속 보완 하 세 요.
class WPromise {
static pending = "pending";
static fulfilled = "fulfilled";
static rejected = "rejected";
constructor(executor) {
this.status = WPromise.pending; // pending
this.value = undefined; // this._resolve
this.reason = undefined; // this._reject
// then
// ? Promise then
this.callbacks = [];
executor(this._resolve.bind(this), this._reject.bind(this));
}
// onFulfilled
// onRejected
then(onFulfilled, onRejected) {
//
//
this.callbacks.push({
onFulfilled,
onRejected,
});
}
_resolve(value) {
this.value = value;
this.status = WPromise.fulfilled; //
//
this.callbacks.forEach((cb) => this._handler(cb));
}
_reject(reason) {
this.reason = reason;
this.status = WPromise.rejected; //
this.callbacks.forEach((cb) => this._handler(cb));
}
_handler(callback) {
const { onFulfilled, onRejected } = callback;
if (this.status === WPromise.fulfilled && onFulfilled) {
//
onFulfilled(this.value);
}
if (this.status === WPromise.rejected && onRejected) {
//
onRejected(this.reason);
}
}
}
이때 의 Promise 는 이미 초기 형 태 를 갖 추 었 으 니, 지금 은 간단하게 테스트 해 볼 수 있다.
function fetchData(success) {
return new WPromise((resolve, reject) => {
setTimeout(() => {
if (success) {
resolve("willem");
} else {
reject('error');
}
}, 1000);
});
}
fetchData(true).then(data => {
console.log(data); // after 1000ms: willem
});
fetchData(false).then(null, (reason) => {
console.log(reason); // after 1000ms: error
});
위의 출력 결 과 를 보면 당분간 아무런 문제 가 없다.다음은 중점적으로 주목 해 야 할 체인 호출 문제 다.
중 난점: 체인 호출
이 걸 보고 무슨 생각 을 했 는 지 모 르 겠 지만 난 어차피 jQuery 가 생각 났 어.사실 체인 호출 은 하나의 인 스 턴 스 를 되 돌려 주 는 것 일 뿐 입 니 다. 먼저 생각 나 는 것 은 바로 돌아 가 는 것 입 니 다
. 그러나 어쨌든 자신 이 정말 괜 찮 습 니까?우 리 는
this
에서 테스트 를 진행 해도 무방 하 다.function fetchData() {
return new WPromise((resolve, reject) => {
setTimeout(() => {
resolve('willem');
}, 1000);
});
}
const p1 = fetchData().then(data1 => {return data1 + ' wei'});
const p2 = p1.then((data2) => {console.log(data2);}); // willem 'willem wei'
const p3 = p1.then((data3) => {console.log(data3);}); // willem 'willem wei'
분명히 this 로 직접 돌아 가 는 것 은 틀 렸 을 것 입 니 다. 함수 의 반환 값 을 처리 해 야 합 니 다.이 럴 때 어떤 친구 가 말 할 수 있 습 니 다. 그럼 제 가 처리 하면 끝 이 잖 아 요. 제 가 then 리 턴 함수 의 집행 결 과 를 value 에 할당 하면 끝 이 잖 아 요.답 은 당연히 부정 적 이다. 이번 에는 Promise 내부 의 value 와 callbacks 의 혼란 을 야기 했다.
그러면 우리 가 채택 한 것 은 당연히 다른 방안 이다.
then return this;
이것 은 간단 한 then 데이터 의 방향 이다.간단하게 말 하면 then 함수 에서 돌아 오 는 Promise 의 value 값 은 현재 then 함수 의 onFulfilled 함수 (첫 번 째 매개 변수) 의 실행 결과 then Promise
에서 유래 합 니 다.우리 가 쓴 코드 를 보면 value 값 은 resolve 함수 에서 만 부 여 됩 니 다. 분명히 우 리 는 onFulfilled 가 실행 한 결 과 를 resolve 의 실행 을 통 해 다음 Promise 에 전달 할 것 입 니 다.
체인 호출 처리 추가:
class WPromise {
static pending = "pending";
static fulfilled = "fulfilled";
static rejected = "rejected";
constructor(executor) {
this.status = WPromise.pending; // pending
this.value = undefined; // this._resolve
this.reason = undefined; // this._reject
// then
// ? Promise then
this.callbacks = [];
executor(this._resolve.bind(this), this._reject.bind(this));
}
// onFulfilled
// onRejected
then(onFulfilled, onRejected) {
// Promise
return new WPromise((nextResolve, nextReject) => {
// Promsie resolve reject callback
// onFulfilled nextResolve Promise value
this._handler({
nextResolve,
nextReject,
onFulfilled,
onRejected
});
});
}
_resolve(value) {
this.value = value;
this.status = WPromise.fulfilled; //
//
this.callbacks.forEach((cb) => this._handler(cb));
}
_reject(reason) {
this.reason = reason;
this.status = WPromise.rejected; //
this.callbacks.forEach((cb) => this._handler(cb));
}
_handler(callback) {
const { onFulfilled, onRejected, nextResolve, nextReject } = callback;
if (this.status === WPromise.pending) {
this.callbacks.push(callback);
return;
}
if (this.status === WPromise.fulfilled) {
//
// onFulfilled , undefined
const nextValue = onFulfilled ? onFulfilled(this.value) : undefined;
nextResolve(nextValue);
return;
}
if (this.status === WPromise.rejected) {
//
//
const nextReason = onRejected ? onRejected(this.reason) : undefined;
nextResolve(nextReason);
}
}
}
우 리 는 다시 시작 한 예 를 가지 고 와 서 테스트 를 해 보 자.
function fetchData() {
return new WPromise((resolve, reject) => {
setTimeout(() => {
resolve('willem');
}, 1000);
});
}
fetchData().then((data) => {
// after 1000ms
console.log(data); // willem
return 'wei';
}, (err) => {}).then((data2) => {
console.log(data2); // wei
});
좋아, 문제 없어.그러나 위의 버 전 은 처리 되 지 않 은 문제 가 있 습 니 다. onFulfilled 가 실 행 된 결 과 는 간단 한 값 이 아니 라 Promise 일 때 다음 then 은 실 행 된 후에 실 행 됩 니 다.
Promise 기본 판 최종 판:
class WPromise {
static pending = 'pending';
static fulfilled = 'fulfilled';
static rejected = 'rejected';
constructor(executor) {
this.status = WPromise.pending; // pending
this.value = undefined; // this._resolve
this.reason = undefined; // this._reject
// then
// ? Promise then
this.callbacks = [];
executor(this._resolve.bind(this), this._reject.bind(this));
}
// onFulfilled
// onRejected
then(onFulfilled, onRejected) {
// Promise
return new WPromise((nextResolve, nextReject) => {
// Promsie resolve reject callback
// onFulfilled nextResolve Promise value
this._handler({
nextResolve,
nextReject,
onFulfilled,
onRejected
});
});
}
_resolve(value) {
// onFulfilled Promise
//
// value instanof WPromise , Promise Promise
// then Promise( Promise)
// value value ( ,value promise , value )
// value value , value.then onFulfilled
// value , Promise value value value
if (value instanceof WPromise) {
value.then(
this._resolve.bind(this),
this._reject.bind(this)
);
return;
}
this.value = value;
this.status = WPromise.fulfilled; //
//
this.callbacks.forEach(cb => this._handler(cb));
}
_reject(reason) {
if (reason instanceof WPromise) {
reason.then(
this._resolve.bind(this),
this._reject.bind(this)
);
return;
}
this.reason = reason;
this.status = WPromise.rejected; //
this.callbacks.forEach(cb => this._handler(cb));
}
_handler(callback) {
const {
onFulfilled,
onRejected,
nextResolve,
nextReject
} = callback;
if (this.status === WPromise.pending) {
this.callbacks.push(callback);
return;
}
if (this.status === WPromise.fulfilled) {
//
// onFulfilled ,value
const nextValue = onFulfilled
? onFulfilled(this.value)
: this.value;
nextResolve(nextValue);
return;
}
if (this.status === WPromise.rejected) {
//
//
const nextReason = onRejected
? onRejected(this.reason)
: this.reason;
nextReject(nextReason);
}
}
}
오케이, 테스트 해 봐.
function fetchData() {
return new WPromise((resolve, reject) => {
setTimeout(() => {
resolve('willem');
}, 1000);
});
}
fetchData().then((data) => {
return new WPromise(resolve => {
setTimeout(() => {
resolve(data + ' wei');
}, 1000);
});
}, (err) => {}).then((data2) => {
console.log(data2); // willem wei
});
이로써 간단 한 Promise 가 완성 되 었 습 니 다. 물론 처리 해 야 할 것 이 많 습 니 다. 예 를 들 어 이상 등 입 니 다.다음 글 은 우리 함께 다시 한 번
,
의 실현 을 배 워 봅 시다.더 보기: 상기 아 날로 그 Promise 의 전체 코드
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
101 시리즈: 프라미스 #2: 현재 프라미스 상태를 얻고 자신만의 프라미스 큐를 만드는 방법?더 복잡한 주제에 도달하기 전에 Promise 위에 만들 수 있는 도구와 유틸리티 기능에 대해 생각해 볼 것을 제안합니다. 이 기사에서는 현재 약속 상태를 가져오고 약속 대기열을 만드는 방법에 대해 생각해 보겠습니다...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.