2017-11-27 5 views
0

私はredux-observableを使用しています。redux-observableでforkJoinを正しく使うには?

すべての添付ファイルを別々にアップロードした後にメールを送信しようとしています。

このプロセスは、メールAPIを送信

  1. はドラフト
からメールを送って、一旦全ての添付ファイルがアップロードされているドラフト
  • に別々に添付ファイルを追加
  • ドラフトにメールの内容を追加しています

    以下のコードは、すべての添付ファイルを個別にアップロードすることができます。しかし、私はそれらをすべて待っている方法を知らない。

    this docを学習した後、私はの使用が必要だと思いますが、この場合正しく使用する方法はわかりませんでした。

    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

    これは私の最終的な解決方法です。

    読み込みファイルもasyncであるため、この解決策には2つの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いいえ、あなたが私たちが提供できる以上にお手伝いしました、ありがとう! –

    関連する問題