2017-11-27 9 views
0

redux-observable을 사용하고 있습니다.redux-observable에서 forkJoin을 올바르게 사용하는 방법은 무엇입니까?

모든 첨부 파일을 별도로 업로드 한 후 메일을 보내려고합니다.

이 보내는 메일 API의 과정은

  1. 일단 모든 첨부 파일이 업로드 초안에 별도로 첨부 파일을 추가 초안에 메일 내용을 추가 초안에서 메일을 보낼 수 있습니다

지금 아래 코드는 모든 첨부 파일을 개별적으로 성공적으로 업로드 할 수 있습니다. 그러나 나는 그들 모두를 기다리는 방법을 모른다.

this doc을 학습 한 후에는 forkJoin을 사용해야한다고 생각하지만이 경우 올바르게 사용하는 방법을 찾지 못했습니다.

export const addMailContentSucceedEpic = (action$, store) => 
    action$ 
    .ofType(ADD_MAIL_CONTENT_SUCCEED) 
    .expand(action => {  // expand here helps upload all attachments separately 
     const restAttachments = removeFirstAttachment(action.payload.attachments); 

     if (isEmpty(restAttachments)) return Observable.empty(); 

     return Observable.of({ 
     ...action, 
     payload: { 
      ...action.payload, 
      attachments: restAttachments 
     } 
     }); 
    }) 
    .map(action => addAttachment({ mailId: action.payload.mailId, attachment: first(action.payload.attachments) })); 

export const addAttachmentEpic = (action$, store) => 
    action$ 
    .ofType(ADD_ATTACHMENT) 
    .mergeMap(action => getBase64FromFile(action)) 
    .mergeMap(action => 
     ajax 
     .patch(url, { base64: action.payload.base64 }) 
     .map(() => addAttachmentSucceed({ mailId: action.payload.mailId })) 
     .catch(addAttachmentFailed) 
    ); 

export const addAttachmentSucceedEpic = (action$, store) => 
    action$ 
    .ofType(ADD_ATTACHMENT_SUCCEED) 
    // Here is wrong, I need wait all attachments be uploaded 
    // I tried to add a global `let = tasks$[];` on the top, but I am not clear where and how I can push each task (add attachment) to it 
    // Then add .mergeMap(action => Observable.forkJoin(tasks$)) here, but it probably wrong to be added after .ofType(ADD_ATTACHMENT_SUCCEED) 
    // In my mind, it needs to be after something `ADD_ALL_ATTACHMENTS_SUCCEED` 
    .map(action => sendMailFromDraft({ mailId: action.payload.mailId })); 

UPDATE :

나는 아래의 구조를 변경하려고합니다.

아마도 addAttachments$을 페이로드 (?)로 전달하거나 전역 변수로 만들 수 있습니다. 나중에 더 많은 업데이트를 제공 할 것입니다.

const addAttachments$ = [ 
    ajax.patch(url, { base64: getBase64(first(action.payload.attachments) })), 
    ajax.patch(url, { base64: getBase64(second(action.payload.attachments) })), 
    ajax.patch(url, { base64: getBase64(third(action.payload.attachments) })), 
    // ... 
]; 

export const addMailContentSucceedEpic = (action$, store) => 
    action$ 
    .ofType(ADD_MAIL_CONTENT_SUCCEED) 
    .mergeMap(action => 
     Observable.forkJoin(addAttachments$) 
     .map(() => sendMailFromDraft({ mailId: action.payload.mailId })) 
    ) 
    .catch(/* ... */); 
+0

을 확인하십시오? – martin

+0

@martin 그냥 더 추가했습니다! –

답변

1

이것이 나의 최종 해결책입니다.

읽기 파일도 비동기이므로이 솔루션에는 두 개의 forkJoin이 있습니다.

forkJoin은 모든 파일을 읽는 동안 기다리는 데 사용됩니다. forkJoin은 모든 첨부 파일이 업로드되기를 기다리는 데 사용됩니다.

코드에 getBase64FromFile$를 들어

, 당신은 당신의 코드에서`forkJoin`이 How to handle async function in redux-observable?

export const addMailContentSucceedEpic = (action$, store) => 
    action$ 
    .ofType(ADD_MAIL_CONTENT_SUCCEED) 
    .mergeMap(action => addTasks$(action)) 
    .mergeMap(action => Observable.forkJoin(action.payload.posts$) 
     .map(() => sendMailFromDraft({ mail: action.payload.mail })) 
    ); 


function getPosts(base64Array, action) { 
    let posts$ = []; 

    for (let i = 0; i < base64Array.length; ++i) { 
    posts$ = [...posts$, ajax.patch(url, { base64: base64Array[i] })]; 
    } 

    return { 
    ...action, 
    payload: { 
     ...action.payload, 
     posts$ 
    } 
    }; 
} 

function addTasks$(action) { 
    let readFiles$ = []; 

    for (let i = 0, attachmentIds = Object.keys(action.payload.attachments); i < attachmentIds.length; ++i) { 
    const attachmentId = attachmentIds[i]; 
    const attachment = action.payload.attachments[attachmentId]; 

    readFiles$ = [...readFiles$, getBase64FromFile$(attachment)]; 
    } 

    return Observable.forkJoin(readFiles$) 
    .map(base64Array => getPosts(base64Array, action)); 
} 
+1

돌아와서 솔루션을 추가해 주셔서 감사합니다! 후손에게 매우 도움이됩니다. – jayphelps

+0

@jayphelps 아니, 우리가 제공 할 수있는 것 이상으로 우리를 도왔습니다. 고마워요! –