대범하게

[Typescript] Promise - async, await 범위 설정하기 본문

Development/Javascript | Typescript

[Typescript] Promise - async, await 범위 설정하기

대범하게 2023. 9. 8. 11:35
반응형

Promise - async, await 범위 설정하기

아래 글은 async와 await 범위 설정에 따라 결과값이 달랐던 부분을 기록하기 위한 글이다.

 

두 코드 모두 HTML5 Canvas에서 생성된 이미지를 블롭(blob) 형태로 만들어서 AWS S3에 업로드하는 기능을 수행한다.

 

수정 전 (uploadMaskingImageFile 함수)

// canvas 위의 masking된 이미지를 s3에 업로드하는 함수
  const uploadMaskingImageFile = async () => {
      const image = new Image();
      if (canvasRef.current && imageData) {
          const canvas = canvasRef.current;
          const context = canvas.getContext('2d');
          if (context) {
              canvas.toBlob(async (blob) => {
                  if (blob) {
                      const file = new File([blob], 'masking.png', { type: blob.type });
	                    const maskingPath = await onFileUpload(file, () => { }); // s3로 파일을 업로드
                      let imageInformation: ImageInfo = {
                        id: undefined,
                        parentId: null,
                        prompt: inputPrompt,
                        image: maskingPath!
                    };
                    return imageInformation;
              });
          }
      } else {
          alert("마스킹된 이미지가 없습니다.");
      }
  };
  1. canvasRef가 존재하고 imageData가 존재하는지 확인한다.
  2. canvas 및 2D 컨텍스트를 얻어온다.
  3. Canvas를 블롭(blob) 형태로 변환한다.
  4. 블롭을 이용하여 새로운 File 객체를 생성한다.
  5. 생성된 파일을 AWS S3에 업로드하기 위해 onFileUpload 함수를 호출한다.
  6. 업로드된 파일 경로를 변수 maskingPath에 저장한다.
  7. 이미지 정보를 담는 객체를 생성하고, 이 정보를 반환한다.

문제가 없어 보이는 코드이지만, 계속해서 maskingPath이 undefined이 나왔다.

 

 

수정 후 (uploadMaskingImageFile 함수)

// canvas 위의 masking된 이미지를 s3에 업로드하는 함수
const uploadMaskingImageFile = async () => {
    if (canvasRef.current && imageData) {
        const canvas = canvasRef.current;
        const context = canvas.getContext('2d');
        if (context) {
            const _blob: Blob = await new Promise<Blob>(async (res, rej) => {
                canvas.toBlob(async (blob) => {
                    if (blob) {
                        res(blob);
                        return;
                    }
                    rej(new Error('Failed to create blob.'));
                });
            });
            const file = new File([_blob], 'masking.png', { type: _blob.type });
            const maskingPath = await onFileUpload(file, () => { }); // s3로 파일을 업로드
            let imageInformation: ImageInfo = {
                id: undefined,
                parentId: null,
                prompt: inputPrompt,
                image: maskingPath!
            };
            return imageInformation;
        } else {
            alert("마스킹된 이미지가 없습니다.");
            throw new Error("Canvas context is not available.");
        }
    } else {
        alert("마스킹된 이미지가 없습니다.");
        throw new Error("Canvas or image data is not available.");
    }
};
  1. canvasRef가 존재하고 imageData가 존재하는지 확인한다.
  2. canvas 및 2D 컨텍스트를 얻어온다.
  3. canvas.toBlob 메소드를 사용하여 Canvas를 블롭(blob) 형태로 변환한다. 이 부분에서 Promise를 사용하여 블롭 생성 과정을 감싸고 있다.
  4. 생성된 블롭을 이용하여 새로운 File 객체를 생성한다.
  5. 생성된 파일을 AWS S3에 업로드하기 위해 onFileUpload 함수를 호출한다.
  6. 업로드된 파일 경로를 변수 maskingPath에 저장한다.
  7. 이미지 정보를 담는 객체를 생성하고, 이 정보를 반환한다.

문제는 blob이었다.

 

수정 전 코드에서 canvas.toBlob 메소드를 사용하여 Canvas를 블롭(blob) 형태로 변환하는 과정에서 문제가 있었다.

 

수정 전의 코드에서 async/await를 걸어서 문제없이 처리했다고 생각했지만, blob 형태로 변환하는 과정 역시도 비동기적으로 처리해도 되는지, 동기적으로 처리해도 되는지에 대해 고려해야하는 부분이었다.

 

이를 해결하고자 canvas.toBlob 부분을 Promise와 async/await를 사용하여 더 명시적으로 처리함으로써 해결할 수 있었다.

 

결론적으로, 핵심은 한 코드 내에서 비동기적으로 처리되지 않아야한다면 한 번에 async/await로 감싸지말아야한다는 것이다.

Comments