Polyfill 약속

22381 단어 javascript
MDN 설명서를 통해 Promises을 확인하십시오.
또한 바퀴를 재발명하지 말고, 이미 존재하는 기능을 위해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이라고 부른다.
  • 은 최소한 두 개의 속성을 가진 대상을 되돌려야 한다. thencatch
  • thencatch은 다시 리셋을 받는 함수로 그것들도 링크할 수 있다.따라서 둘 다 this
  • 에 대한 인용을 되돌려야 한다
  • 우리는 thencatch에 전달된 리셋 함수에 대한 인용을 집행기의 상태에 따라 향후 시간에 집행할 수 있도록 어디에 저장해야 한다.만약executor가 문제를 해결했다면, 우리는 반드시 then번을 호출해야 한다.만약 실행기가 거절한다면, 우리는 반드시 catch 리셋을 호출해야 한다.
  • 은 간단하게 보기 위해 우리의 약속이 영원히 resolve이라고 가정합시다.따라서 현재 catch의 기능은 없지만 thencatch
  • 과 동일합니다.
  • 에서는 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)
    
    이것은 우리가 집행해야 할 약속의 반격이다.따라서, 우리는 이 집행기 함수를 호출해야 한다. 이 함수는 두 개의 매개 변수인 resolvereject을 받아들일 것이다.
    
    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.resolvePromisePolyFill.reject을 달성하여 PromisePolyFill.all, Promise.resolve, Promise.reject과 같이Promise.allresovle은 매우 단도직입적이다.여기서 우리는 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

    좋은 웹페이지 즐겨찾기