Polyfill 약속
22381 단어 javascript
또한 바퀴를 재발명하지 말고, 이미 존재하는 기능을 위해polyfills를 처음부터 작성해 보지 않도록 주의하세요.이것은 단지 하나의 예로'약속'이 배후에서 어떻게 작동하는지, 그리고 우리 자신을 어떻게 상상해서 더 많은 이해를 얻는지 설명한다.
약속 초기화 예는 다음과 같습니다.
let promise = new Promise((resolve, reject) => setTimeout(() => resolve(1000), 1000));
해결 후 수행해야 할 작업은 다음과 같습니다.promise.then((val) => console.log(val)).catch(err => console.log(err));
polyfill(예를 들어 PromisePolyFill
)을 여러 단계로 나누어 실현합시다.위 코드에 따라 다음과 같은 내용을 알고 있습니다.
executor
이라고 부른다.then
과 catch
then
과 catch
은 다시 리셋을 받는 함수로 그것들도 링크할 수 있다.따라서 둘 다 this
then
과 catch
에 전달된 리셋 함수에 대한 인용을 집행기의 상태에 따라 향후 시간에 집행할 수 있도록 어디에 저장해야 한다.만약executor가 문제를 해결했다면, 우리는 반드시 then
번을 호출해야 한다.만약 실행기가 거절한다면, 우리는 반드시 catch
리셋을 호출해야 한다.resolve
이라고 가정합시다.따라서 현재 catch
의 기능은 없지만 then
과 catch
은 then
에 전달되는 콜백을 onResolve
이라는 변수에 저장할 수 있습니다.
function PromisePolyFill(executor) {
let onResolve;
this.then = function(callback) {
// TODO: Complete the impl
onResolve = callback;
return this;
};
this.catch = function(callback) {
// TODO: We are ignoring this part for simplicity , but its implementation is similar to then
return this;
}
}
처음에 정의한 executor
함수를 살펴보겠습니다.let executor = (resolve, reject) => setTimeout(() => resolve(1000), 1000)
이것은 우리가 집행해야 할 약속의 반격이다.따라서, 우리는 이 집행기 함수를 호출해야 한다. 이 함수는 두 개의 매개 변수인 resolve
과 reject
을 받아들일 것이다.
executor(resolve) // reject scenarios ignored for simplicity
비동기 조작 상태에 따라 집행기는 resolve
또는 reject
을 호출할 것이다.간단하게 보기 위해서, 우리는 여기서 해석 함수만 고려했고, 현재 우리의 약속이 항상 해석된다고 가정했다.현재 우리는 리소스 리셋 함수를 정의해야 한다. 이 함수는 매개 변수로 실행기에 전달된다.우리의 Resolve 함수는 아무것도 아니다. 단지
then
에 전달된 리셋을 촉발할 뿐이다. 우리는 그것을 onResolve
변수에 저장한다 function resolve(val) {
onResolve(val);
}
우리는 이미polyfill의 초기 부분을 완성했다.그래서 지금까지 우리의 현재 함수는 이렇게 보이고 우리의 기본적인 즐거움 경로 장면에 매우 적합하다.우리는
catch
기능을 똑같이 완성할 수 있다.
function PromisePolyFill(executor) {
let onResolve;
function resolve(val) {
onResolve(val);
}
this.then = function(callback) {
// TODO: Complete the impl
onResolve = callback;
return this;
};
this.catch = function(callback) {
// TODO: Complete the impl
return this;
}
executor(resolve);
}
// Sample code for test :
new PromisePolyFill((resolve) => setTimeout(() => resolve(1000), 1000)).then(val => console.log(val));
제2부분
그러나 우리는 집행기 함수가 잠시 후에 작업을 완성하는 상황만 처리했다.executor 함수가 동기화된다고 가정하면
new PromisePolyFill((resolve) => resolve(1000)).then(val => console.log(val));
비동기식 작업(예: fetch
, setTimeout
등)을 수행하지 않고 변수를 직접 확인할 경우 발생할 수 있습니다.우리가 위와 같이
PromisePolyFill
을 호출할 때, 우리는 오류를 얻게 될 것이다.TypeError: onResolve is not a function
이것은 우리의 executor
호출이 우리가 then
리셋의 값을 onResolve
변수에 분배하기 전에 이미 완성되었기 때문이다.따라서 본 예에서 우리는
onResolve
함수에서 resolve
리셋을 실행할 수 없다.반면 then
에 전달된 리콜은 다른 곳에서 집행해야 한다.이제 두 가지 변수가 필요합니다.
fulfilled
: 부울 값, 실행기가 해석되었는지 여부를 표시합니다called
: boolean
, then
의 콜백 여부를 나타냅니다.이제 수정된 내용은 다음과 같습니다.
function PromisePolyFill(executor) {
let onResolve;
let fulfilled = false,
called = false,
value;
function resolve(val) {
fulfilled = true;
value = val;
if(typeof onResolve === 'function') {
onResolve(val);
called = true; // indicates then callback has been called
}
}
this.then = function(callback) {
// TODO: Complete the impl
onResolve = callback;
return this;
};
this.catch = function(callback) {
// TODO: Complete the impl
return this;
}
executor(resolve);
}
//new PromisePolyFill((resolve) => setTimeout(() => resolve(1000), 0)).then(val => console.log(val));
new PromisePolyFill((resolve) => Promise.resolve(resolve(1000)));
이것은 called
을 없앴지만 우리는 여전히 TypeError
방법을 집행하지 않았다.우리는
onResolve
초기화기에서 이 동작을 조건부로 실행해야 한다. 만약에 우리의 리셋이 아직 호출되지 않았고, 약속이 실행되지 않았다면:function PromisePolyFill(executor) {
let onResolve;
let fulfilled = false,
called = false,
value;
function resolve(val) {
fulfilled = true;
value = val;
if (typeof onResolve === "function") {
onResolve(val);
called = true;
}
}
this.then = function (callback) {
onResolve = callback;
if (fulfilled && !called) {
called = true;
onResolve(value);
}
return this;
};
this.catch = function (callback) {
// TODO: Complete the impl
return this;
};
executor(resolve);
}
//new PromisePolyFill((resolve) => setTimeout(() => resolve(1000), 0)).then(val => console.log(val));
new PromisePolyFill((resolve) => resolve(1000)).then(val => console.log(val));
같은 실현을 사용하면 우리도catch 코드를 완성할 수 있다.우리는 this.then
회조와 onReject
블의 값을 가지고 있을 것이다.이것은 연습입니다:)섹션 3:
이제
rejected
, PromisePolyFill.resolve
및 PromisePolyFill.reject
을 달성하여 PromisePolyFill.all
, Promise.resolve
, Promise.reject
과 같이Promise.all
과 resovle
은 매우 단도직입적이다.여기서 우리는 reject
대상을 되돌려주지만, 우리 자신의 집행기 함수를 전달하고, 이 함수를 강제로 해석/거절한다PromisePolyFill.resolve = (val) =>
new PromisePolyFill(function executor(resolve, _reject) {
resolve(val);
});
PromisePolyFill.reject = (reason) =>
new PromisePolyFill(function executor(resolve, reject) {
reject(reason);
});
이제 Promise.all을 달성하겠습니다.이것은 한 그룹의 약속을 입력으로 하고, 그 약속을 한 그룹의 입력 약속의 결과로 해석한다.
PromisePolyFill.all = (promises) => {
let fulfilledPromises = [],
result = [];
function executor(resolve, reject) {
promises.forEach((promise, index) =>
promise
.then((val) => {
fulfilledPromises.push(true);
result[index] = val;
if (fulfilledPromises.length === promises.length) {
return resolve(result);
}
})
.catch((error) => {
return reject(error);
})
);
}
return new PromisePolyFill(executor);
};
여기에서, 우리는executor 함수를 다시 만들고, 이executor를 받을promise 대상을 되돌려줍니다.수행자의 기능은 다음과 같습니다.
PromisePolyFill
이라는 그룹을 유지하고 그 어떠한 약속이 해결될 때 그 값을 전달합니다.fulfilledPromises
) fulfilledPromises.length === promises.length
을 호출합니다.resolve
을 호출합니다Github
Reference
이 문제에 관하여(Polyfill 약속), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/vijayprwyd/polyfill-for-promises-1f0e텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)