promise.allSettled 직접 구현

DY·2024년 5월 21일
0

JavaScript

목록 보기
13/13

원리

then의 반환값이 resolve나 reject호출 없이 값만 반환하면 fulfilled상태 즉 resolve가 호출된상태로 새로운 Promise를 만드는 방법을 이용함.

const promiseAllSettled = (promises) => {
    return Promise.all(promises.map(p => 
        p.then(
            value => ({ status: 'fulfilled', value }),
            reason => ({ status: 'rejected', reason })
        )
    ));
};

// 예제 Promise 배열
const promises = [
    new Promise(resolve => setTimeout(() => resolve('Result 1'), 1000)),
    new Promise((_, reject) => setTimeout(() => reject('Error 2'), 500)),
    new Promise(resolve => setTimeout(() => resolve('Result 3'), 1500))
];

console.time('promiseAllSettled');
promiseAllSettled(promises).then(results => {
    console.timeEnd('promiseAllSettled');
    console.log(results);
});

활용

이미지 URL string 배열을 이미지 객체로 변환

// Base64 형식의 Data URL 예제 배열
const dataURLs = [
    "data:image/png;base64,iVBORw0KGgoAAAANSUACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAEvPSURBVHhe7b13lFVV9u/bvza...
    // 다른 dataURL들...
];

// 이미지 로드를 비동기적으로 처리하는 함수
const loadImage = (dataURL, maxRetries = 3) => {
    return new Promise((resolve, reject) => {
        let retryCount = 0;
        const img = new Image();

        img.onload = () => {
            console.log("이미지가 로드되었습니다.");
            resolve(img);
        };

        img.onerror = (err) => {
            if (retryCount < maxRetries) {
                console.warn(`이미지 로드 중 오류 발생. 재시도 중 (${retryCount + 1}/${maxRetries})...`);
                retryCount++;
                setTimeout(() => {
                    img.src = ""; // src를 비운 후 다시 설정 (트릭)
                    img.src = dataURL;
                }, 1000); // 1초 후에 다시 시도
            } else {
                console.error("이미지 로드 중 오류 발생:", err);
                reject(err);
            }
        };

        img.src = dataURL;
    });
};

// Promise.allSettled의 폴리필 구현
const promiseAllSettled = (promises) => {
    return Promise.all(promises.map(p => 
        p.then(
            value => ({ status: 'fulfilled', value }),
            reason => ({ status: 'rejected', reason })
        )
    ));
};

// 모든 이미지를 비동기적으로 로드
const loadAllImages = async (dataURLs) => {
    const imagePromises = dataURLs.map(dataURL => loadImage(dataURL));
    
    const results = await promiseAllSettled(imagePromises);
    const successfulImages = results.filter(result => result.status === 'fulfilled').map(result => result.value);
    const failedResults = results.filter(result => result.status === 'rejected');

    console.log(`${successfulImages.length}개의 이미지가 성공적으로 로드되었습니다.`);
    console.log(`${failedResults.length}개의 이미지 로드에 실패했습니다.`);
};

// 이미지 로드 시작
loadAllImages(dataURLs);
profile
화면에 보이는 모든것에 관심이 있습니다. 개발하면서 고민했던것들, 공부했던걸 기록하는 저장소입니다.

0개의 댓글