약속을 반환하는 함수를 사용하여 배열 필터링

부울 값 대신 부울 값을 반환하는 함수를 사용하여 값 배열을 필터링하려는 경우 상황이 흥미로워집니다.

전제 조건:


  • 약속이 어떻게 작동하는지에 대한 기본적인 이해.
  • Typescript의 기본 지식.

  • 부울을 반환하는 함수를 사용하여 값 배열을 필터링하는 것은 쉽습니다. 예제를 보자.

    const values = [1, 2, 3, 4, 5, 6];
    const isEven = (v: number) => v % 2 === 0;
    const result = values.filter(isEven);
    console.log(result);
    
    // Output
    // [ 2, 4, 6 ]
    


    위의 코드에서 isEven라는 함수를 사용하여 숫자 배열을 필터링하고 짝수만 반환합니다. isEven 함수는 number를 취하고 숫자가 짝수인지 아닌지를 나타내는 boolean 값을 반환한다는 것을 알고 있습니다.
    isEven 함수를 변경하여 Promise<boolean> 대신 boolean를 반환하고 값을 필터링해 보겠습니다.

    const values = [1, 2, 3, 4, 5, 6];
    const isEvenPromise = (v: number) => new Promise(res => res(v % 2 === 0));
    const result = values.filter(isEvenPromise);
    
    // Output
    // [1, 2, 3, 4, 5, 6]
    


    보시다시피 출력에서 ​​모든 값을 얻었습니다. 이는 잘못된 것입니다. 자, 왜 그런 일이 일어났습니까?

    이것은 Promise 함수가 아니라 isEvenPromise 함수를 실행한 결과로 필터가 boolean를 얻었기 때문에 발생했습니다. 자바 스크립트의 진실한 개념에 따라 객체는 항상 true 이므로 모든 값이 출력으로 반환됩니다.

    이제 우리는 문제가 무엇인지 알았습니다. 그러나 이것을 해결하는 방법은 무엇입니까? 이를 해결하기 위한 함수를 작성해 보자.

    먼저, 함수가 어떻게 생겼는지에 대한 명확한 아이디어를 얻기 위해 함수의 유형을 정의합시다.

    type Filter = <T>(values: T[], fn: (t: T) => Promise<boolean>) => Promise<T[]>;
    


  • 첫 번째 매개변수는 필터링해야 하는 values 유형의 T 배열입니다.
  • 두 번째 매개변수는 T 유형의 값을 입력으로 받아들이고 Promise 유형의 boolean 를 반환하는 함수입니다.
  • 반환 유형은 Promise 이며, T 유형의 배열을 보유합니다.

  • 한 가지 주의할 점은 이 함수의 반환 유형은 T[]가 아니라 Promise<T[]>라는 것입니다. 이는 필터 함수가 boolean 를 반환하지 않고 Promise<boolean> 를 반환하기 때문입니다. Promise 에서 값을 제거할 수 없습니다. Promise에서 반환된 값을 사용하는 유일한 방법은 then를 사용하거나 asyncawait를 사용하는 것입니다.

    이제 함수의 본문을 작성해 보겠습니다.

    const filterPromise: Filter = async (values, fn) => {
        const promises = values.map(fn);                // Line 1
        const booleans = await Promise.all(promises);   // Line 2
        return values.filter((_, i) => booleans[i]);    // Line 3
    };
    


    여기서 한 가지 중요한 점은,

    filter function in JS passes the index of the array as a second argument to the accepted function.


    Line 1 에서 map 값 배열을 직접 필터링하는 대신 fn 값을 boolean 먼저 얻을 수 있도록 합니다. Line 2 에서 우리는 boolean 배열을 보유하고 있는 Promise 배열을 Promise로 변환합니다. 여기에서 await 키워드를 사용하여 booleans 에 액세스합니다. Line 3 에서 values 번째 요소의 부울 값을 보유하는 i 배열의 booleans 번째 요소를 사용하여 i를 필터링합니다.

    각 행의 실행 결과로 각 변수가 보유하게 될 내용은 아래에 나와 있습니다.

    입력 값의 경우[1, 2, 3, 4, 5, 6],

    1행:




    // As a result of Line 1
    const promises = [
        Promise<false>,
        Promise<true>,
        Promise<false>,
        Promise<true>,
        Promise<false>,
        Promise<true>,
    ]
    


    2행:




    // As a result of Line 2
    const booleans = [
        false,
        true,
        false,
        true,
        false,
        true
    ]
    


    3행:




    // Return at Line 3
    Promise<[2, 4, 6]>
    


    보시다시피 Line 3의 결과는 입력 배열에서 짝수를 적절하게 필터링합니다.

    전체 코드는 아래와 같습니다.

    const values = [1, 2, 3, 4, 5, 6];
    const isEvenPromise = (v: number): Promise<boolean> => new Promise(res => res(v % 2 === 0));
    
    type Filter = <T>(values: T[], fn: (t: T) => Promise<boolean>) => Promise<T[]>;
    const filterPromise: Filter = async (values, fn) => {
        const promises = values.map(fn);                // Line 1
        const booleans = await Promise.all(promises);   // Line 2
        return values.filter((_, i) => booleans[i]);    // Line 3
    };
    
    const result = filterPromise<number>(values, isEvenPromise);
    
    result.then(d => console.log(d));
    
    // Output
    // [ 2, 4, 6 ]
    


    저처럼 한 라이너의 팬이라면 filterPromise 함수를 아래와 같이 한 줄로 작성할 수 있습니다.

    const filterPromise = (values, fn) => 
        Promise.all(values.map(fn)).then(booleans => values.filter((_, i) => booleans[i]));
    


    당신이 즐겼기를 바랍니다! 해피 해킹!

    좋은 웹페이지 즐겨찾기