Polyfill: Promise.five() 만들기

Polyfill 질문은 Javascript 인터뷰에서 일반적입니다. 가장 일반적인 것 중 일부는 다음과 같습니다.
  • Array.map
  • Array.reduce
  • Promise.all
  • Promise.any

  • 등.

    얼마 전에 Promise.five와 유사하지만 미묘한 차이가 있는 Promise.all 폴리필을 생성하라는 요청을 받았습니다.

    이 게시물은 인터뷰에서 질문을 받았을 때 유사한 질문에 대처할 수 있는 방법에 대한 글입니다.

    질문: 단일 숫자를 인수로 받는 minPromises라는 함수를 만듭니다. 해당 인수를 기반으로 Promise.five() 또는 Promise.three()로 사용할 수 있는 함수를 생성합니다. 예: Promise.three()는 Promise.all()과 유사합니다. Promise 목록을 가져오고 적어도 세 개의 Promise가 해결되면 반환합니다.

    첫 번째 생각



    적어도 min 약속이 해결될 때까지 기다려야 할 것 같습니다. 따라서 반드시 카운터가 필요합니다.

    숫자를 받아서 다른 함수를 반환하는 고차 함수를 만들어야 합니다. 해당 함수는 다음과 같은 Promise 클래스의 새 정적 속성에 할당할 수 있습니다.

    Promise.three = {}
    Promise.four = {}
    


    발생할 수 있는 의심:


  • What if Promise.four()가 길이가 3인 약속 배열과 함께 사용됩니다.
  • 모든 약속 실패에 대한 이유 또는 실패에 대한 일반적인 응답과 함께 약속을 거부해야 합니까?
  • 반환 배열 길이가 동일해야 합니까? 일부 약속은 최종 결과에 사용되지 않습니다. 인덱스에서 반환되어야 하는 것.

  • 내 면접관은 다음과 같이 정리했습니다.
  • 바로 거절하세요.
  • 샘플 문자열이 있는 일반적인 거부가 작동합니다.
  • 비어 있음/null/정의되지 않음. 아무것. 그러나 배열 순서는 Promise.all 와 같이 유지되어야 합니다.

  • 초기 코드:



    먼저 가장 안쪽의 기능부터 시작합니다. min 변수가 있습니다. 약속을 반복할 수 있습니다. 해결된 모든 약속에 대해 성공 카운터가 증가합니다. 거부된 약속마다 실패 카운터를 늘립니다.

    const min = 3;
    
    function minPromise (promises) {
    
        return new Promise((resolve, reject) => {
            if (min > promises.length) return resolve("error");
    
            let counter = 0;
            let errCounter = 0;
    
            promises.forEach((promise) => {
                promise.then((res) => {
               //increase counter
    }).catch((res) => {
              //increase errCounter
    });
            });
    
        });
    
    }
    


    상태 확인:



    이제 카운터를 증가시키는 코드를 입력할 수 있습니다. 결과 형성도 시작해야 합니다. 이를 위해서는 다른 array가 필요합니다. 또한 각 약속의 올바른 색인이 필요하므로 forEach 콜백의 두 번째 매개변수를 사용해야 합니다.

    const min = 3;
    
    function minPromise (promises) {
    
        return new Promise((resolve, reject) => {
            if (min > promises.length) return resolve("error");
    
            let counter = 0;
            let errCounter = 0;
            let resolvedValues = [];
            promises.forEach((promise, index) => {
                promise.then((res) => {
                    counter++;
                    resolvedValues[index] = res;
                    if (counter === min) {
                        resolve(resolvedValues);
                    }
                }).catch((res) => {
                    errCounter++;
                });
            });
    
        });
    
    }
    


    케이스 거부:



    이 약속은 언제 거부됩니까?
  • min가 유효하지 않은 경우 및
  • countermin가 될 수 없는 거부된 약속이 충분히 있을 때

  • const min = 3;
    
    function minPromise(promises) {
    
        return new Promise((resolve, reject) => {
            if (min > promises.length) return reject("error");
    
            let counter = 0;
            let errCounter = 0;
            let resolvedValues = new Array(promises.length);
            promises.forEach((promise, index) => {
                promise.then((res) => {
                    counter++;
                    resolvedValues[index] = res;
                    if (counter === min) {
                        resolve(resolvedValues);
                    }
                }).catch((res) => {
                    errCounter++;
                    if (errCounter > promises.length - min) {
                        reject("error");
                    }
                })
            });
        });
    
    }
    


    참고: 반환 앞에 거부를 추가해야 했습니다. 그렇지 않으면 Promise 흐름이 계속됩니다. 모든 흐름은 return 문에 도달하거나 오류가 발생할 때까지 끝까지 계속됩니다. 안SO answer, 같은 설명.

    모든 것을 마무리합니다(말장난 의도):



    위의 코드가 좋아 보입니다. 이제 min를 입력으로 받아들이고 다른 버전을 생성할 수 있는 함수로 래핑해야 합니다. 클로저를 사용하면 쉽게 할 수 있습니다.

    const minPromises = (min) => {
    
        return function(promises) {
    
            return new Promise((resolve, reject) => {
                if (min > promises.length) return reject("error");
    
                let counter = 0;
                let errCounter = 0;
                let resolvedValues = new Array(promises.length);
                promises.forEach((promise, index) => {
                    promise.then((res) => {
                        counter++;
                        resolvedValues[index] = res;
                        if (counter === min) {
                            resolve(resolvedValues);
                        }
                    }).catch((res) => {
                        errCounter++;
                        if (errCounter > promises.length - min) {
                            reject("error");
                        }
                    })
                });
            });
    
        }
    }
    


    이제 위의 내용을 다음과 같이 사용할 수 있습니다.

    Promise.four = minPromises(4);
    Promise.six = minPromises(6);
    


    그리고 그게 다야. 끝났습니다.

    보적



    이 질문은 클로저, 커링, 물론 약속과 같은 많은 개념을 다루었습니다. 주요 아이디어는 개별 약속이 해결되거나 거부될 때 조치를 취하는 것입니다.

    이와 같은 작업은 샘플Promise.all 폴리필을 수행한 경우 확실히 더 쉽습니다. 솔루션은 async await/.then 대신 .catch 도 사용할 수 있습니다. 인터뷰를 하면서 알 수 있었던 것입니다.

    A codepen link

    이에 대한 어떤 종류의 피드백도 기쁘게 생각합니다. 이 문제를 어떻게 해결했을지 알려주시겠습니까?

    좋은 웹페이지 즐겨찾기