[Redux] redux-saga 처음 실행된 함수만 실행되고 그다음에는 취소/경고
23337 단어 redux sagaredux비동기redux
파일 다운로드를 연속으로 했을 때 두번째 액션 부터 취소하고 토스트 보여주어야 하는 상황
- 특정 액션이 연속 해서 일어났을 때 이전 액션 취소되고 가장 마지막에 실행된 액션이 실행되는 takeLatest의 경우, 처음으로 시작된 액션이 시작되는 것이 아닌 가장 마지막에 실행된 액션이 실행되는 것이기에 맞지 않음
→ 처음 액션이 실행되고 그 후 액션이 취소 되어야함
// action types
const DOWNLOAD_FILE_START = "DOWNLOAD_FILE_START" as const;
const DOWNLOAD_FILE_SUCCESS = "DOWNLOAD_FILE_SUCCESS" as const;
const DOWNLOAD_FILE_FAILURE = "DOWNLOAD_FILE_FAILURE" as const;
//action creators
const downloadFileStart = (file:{url:string,fileName:string}) => ({
type: DOWNLOAD_FILE_START
payload: file
});
const downloadFileSuccess = () => ({
type: DOWNLOAD_FILE_SUCCESS
});
const downloadFileFailure = (error:{status:number}) => ({
type: DOWNLOAD_FILE_FAILURE,
payload: error
});
- 작성해본 코드 ( 문제 발생 )
function* downloadFile({payload}:ReturnType<typeof downloadFileStart>):Generator<StricEffect,void,never>{
const {url,fileName} = payload;
try{
... //download file from url
yield put(downloadFileSuccess());
}catch(error){
yield put(downloadFileFailure(error));
}
}
function* monitorActionOfDownloadFileStart(){
while(yield take(DOWNLOAD_FILE_START)){ //DOWNLOAD_FILE_START 액션이 실행되면 while문 실행
const downloadStartTask = yield fork(downloadFile); //downloadFile함수 실행 (다운로드 시작)
const {start,success,failure}:{start:ReturnType<typeof downloadFileStart>,success:ReturnType<typeof downloadFileSuccess>,failure:ReturnType<typeof downloadFileFailure>} = yield race(take(DOWNLOAD_FILE_START),take(DOWNLOAD_FILE_SUCCESS),take(DOWNLOAD_FILE_FAILURE));
if(success || failure) break; //시작보다 성공이나 실패가 더 빨리 실행된다면 시작 액션은 무조건 취소가 되고, while문에서 빠져나옴
if(start){ // 시작이 성공이나 실패보다 더 빨리 실행된다면 성공과 실패 액션을 취소시키므로 안됌!! 성공액션의 경우에는 성공만 알려주지만 실패액션일 경우 "다운로드에 실패했습니다"라는 toast가 나와야하기 때문에 세가지 액션으로 race 사용하면 x
yield cancle(downloadStartTask);
yield put(toggleToast("파일 다운로드 중입니다. 잠시후에 시도해주세요."));
}
}
}
//항상 실행되며 모니터링 하고 있음
function* download(){
yield fork(monitorActionOfDownloadFileStart);
}
function* saga(){
yield all([...,call(download)])
}
- 작성해본 코드 ( 문제 발생 )
function* downloadFile({payload}:ReturnType<typeof downloadFileStart>):Generator<StricEffect,void,never>{
const {url,fileName} = payload;
try{
... //download file from url
yield put(downloadFileSuccess());
}catch(error){
yield put(downloadFileFailure(error));
}
}
function* monitorActionOfDownloadFileStart(){
while(yield take(DOWNLOAD_FILE_START)){ //DOWNLOAD_FILE_START 액션이 실행되면 while문 실행
const downloadStartTask = yield fork(downloadFile); //downloadFile함수 실행 (다운로드 시작)
yield take(DOWNLOAD_FILE_START); // DOWNLOAD_FILE_START 액션이을 기다리고 있다가 또 실행됐다면
yield cancle(downloadStartTask); // download 취소
yield put(toggleToast("파일 다운로드 중입니다. 잠시후에 시도해주세요."));
}
}
}
/*
하지만 DOWNLOAD_FILE_START이 실행되고 성공하거나 실패를 할 때까지 DOWNLOAD_FILE_STAR T이 실행되지 않을 때 파란색 부분까지만 실행된 상황이기 때문에 DOWNLOAD_FILE_START이 실행이 된다면 빨간색 부분이 실행되어 다운로드가 정상적으로 되지 않는 문제 발생
*/
//항상 실행되며 모니터링 하고 있음
function* download(){
yield fork(monitorActionOfDownloadFileStart);
}
function* saga(){
yield all([...,call(download)])
}
- debouncing 이용해보자
import { delay } from 'redux-saga'
function* downloadFile(paylod:{url,fileName}):Generator<StricEffect,void,never>{
try{
... //download file from url
yield put(downloadFileSuccess());
}catch(error){
yield put(downloadFileFailure(error));
}
}
function* watchFileDownload() {
let action;
while (true) {
const downloadFileAction:ReturnType<typeof downloadFileStart> = yield take(DOWNLOAD_FILE_START);
if (action) {
yield put(toggleToast("파일 다운로드 중입니다. 잠시후에 시도해주세요."));
break;
}
action = yield fork(downloadFile,downloadFileAction.payload)
}
}
function* saga(){
yield all([...,call(watchFileDownload)])
}
Author And Source
이 문제에 관하여([Redux] redux-saga 처음 실행된 함수만 실행되고 그다음에는 취소/경고), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@harim/Redux-redux-saga-처음-실행된-함수만-실행되고-그다음에는-취소경고저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)