2017-11-27 2 views
1

나는 RxJS를 사용하고 있고 redux-observable입니다.redux-observable에서 비동기 함수를 처리하는 방법은 무엇입니까?

나는 서사시로 파일을 읽으려고합니다. 제 경우에는 서사시에서해야합니다. 왜냐하면 어떤 다른 서사시는 expand 연산자로이 서사시적인 "알려지지 않은"시간을 트리거하기 때문입니다.

그러나 FileReader가 비동기이기 때문에 아래 코드는 작동하지 않습니다.

RxJS의 올바른 처리 방법은 무엇입니까? 감사합니다

export const uploadAttachmentEpic = (action$, store) => 
    action$ 
    .ofType(UPLOAD_ATTACHMENT) 
    .map(action => { 
     const reader = new FileReader(); 

     reader.onload =() => { 
     return { 
      ...action, 
      payload: { 
      ...action.payload, 
      base64: reader.result 
      } 
     } 
     }; 

     reader.readAsDataURL(action.payload.file); 
    }) 
    .mergeMap(action => 
     ajax 
     .post(/* use action.payload.base64 */) 
     .map(uploadAttachmentSucceed) 
     .catch(uploadAttachmentFailed) 
    ); 
+0

개인적으로 홀 관찰자와 FileReader를 건너 뛰고 동기식으로 더 빠르고 빠르지 않고 [FormData] (https://developer.mozilla.org/en-US/docs/Web/API/FormData)를 사용하면됩니다. 서버가 바이너리 (멀티 파트 업로드)를 처리 할 수 ​​있다면 33 % 더 큰 페이로드 – Endless

+0

@ 끝내 주신 제안에 감사드립니다. 나중에 FormData를 확실히 조사하겠습니다! –

답변

2

팬의 대답은 좋다 중요한 몇 가지주의 사항이 있습니다.

  • 지연된 파일 대신 즉시 파일 읽기가 시작됩니다. 따라서 readFile(file)으로 전화하면 누구나 구독하기 전에 시작됩니다. 누군가가 즉시 동기식으로 구독하지 않을 가능성이 있으므로 reader.onload에서 오류가 발생하기 쉽습니다. Observables는 완벽하게 게으르고 반복적 인 공장으로 이상적입니다.

  • 결코 관찰자에서 obs.complete()을 호출하지 않으므로 구독이 끝나지 않으므로 구독이 메모리 누수가 될 수 있습니다.

  • 옵저버의 메서드는 바인딩되지 않으므로 reader.onerror = obs.error은 실제로 작동하지 않습니다. 대신 e => obs.error(e) 또는 obs.error.bind(obs)See here for reference on why

  • 중 하나가 필요합니다. 구독 취소시 읽지 않음을 취소하지 않습니다. 여기

내가 그것을 할 것입니다 방법은 다음과 같습니다

function readFile(file){ 
    // Could use Observable.create (same thing) but I 
    // prefer this one because Observable.create is 
    // not part of the TC39 proposal 
    return new Observable(observer => { 
    const reader = new FileReader(); 
    reader.onload = (e) => { 
     observer.next(reader.result); 
     // It's important to complete() otherwise this 
     // subscription might get leaked because it 
     // "never ends" 
     observer.complete(); 
    }; 
    reader.onerror = e => observer.error(e); 
    reader.readAsDataURL(file); 

    // unsubscribe handler aka cleanup 
    return() => { 
     // LOADING state. 
     // Calling abort() any other time 
     // will throw an exception. 
     if (reader.readyState === 1) { 
     reader.abort(); 
     } 
    }; 
    }); 
} 

이 패턴은 거의 모든 API에 적용, 그래서 그것이 작동하는 방법을 정확하게 이해하는 것이 매우 편리합니다 할 수 있습니다.


팬이 비평을 신경 쓰지 않기를 바랍니다! 나는 기분을 상하게하려는 것이 아니라 지식을 공유하고 싶습니다.

1

당신의 파일을 읽는 과정에서 Observable이 반환됩니다. 비동기 프로세스가 제대로 처리되지 않았습니다. 나는 먼저 관찰 가능한 것을 반환하는 파일 읽기 함수를 생성 할 것을 제안한다. 다음 flapMap()

function readFile(file){ 
    let reader = new FileReader(); 
     return Observable.create(obs => { 
     reader.onload = function (e) { 
      obs.next(reader.result); 
     }; 
     reader.onerror = obs.error; 
    }) 
     reader.readAsDataURL(file); 
    } 

다음 코드에서 당신이 ..flatMap처럼에 병합 할 수 있습니다에 첨부 (파일 => ReadFile을 (파일)) (이 글을 쓰는 현재)

+0

지금 시도해보고 결과 하나를 알려 드리겠습니다. 'reader.readAsDataURL (file);'에 도달 할 수 없습니다. 내부로 이동해야합니다. –

+0

당신이 플 런커를 만들면 디버깅을 도울 수 있습니다. 내 프로젝트에서 비슷한 코드를 사용했다. 정말 한 방향. –

+0

좋은 작품! RxJS 5에서 또 다른 것은'flatMap'이 아니라'mergeMap'입니다. –

관련 문제