2017-03-26 7 views
6

"yield"문구가 콜백 내에서 허용되지 않기 때문에 콜백 내에서 redux-saga의 "put"기능을 어떻게 사용할 수 있습니까?콜백 내에서 redux-saga의 "yield"를 얻는 방법은 무엇입니까?

나는 다음과 같은 콜백을 가지고 싶습니다이 작동하고 "예기치 않은 토큰"에 종료되지

function onDownloadFileProgress(progress) { 
    yield put({type: ACTIONS.S_PROGRESS, progress}) 
} 

수율가 일반 기능에 사용할 수 없습니다 때문입니다. 그렇지 않으면 "function *"으로 콜백을 전달할 수 없으므로 yield가 허용됩니다. 여기서 ES6이 고장난 것 같습니다.

나는 redux-saga가 "channels"이라고하는 몇 가지 기능을 제공하지만 솔직히 말해서 이해하지 못했습니다. 이 채널과 예제 코드에 대해 여러 번 읽었지만, 모든 예제에서 그들은 매우 어렵고 다른 문제를 해결했지만 단순한 사례는 아니었고 그날 끝났습니다.

누군가가이 문제를 해결하는 방법에 대한 해결책을 말해 줄 수 있습니까?

전체 컨텍스트 :

function onDownloadFileProgress(progress) { 
    yield put({type: ACTIONS.S_PROGRESS, progress}) 
} 

export function * loadFile(id) { 
    let url = `media/files/${id}`; 

    const tempFilename = RNFS.CachesDirectoryPath + '/' + id; 

    const download = RNFS.downloadFile({ 
    fromUrl: url,   
    toFile: tempFilename, 
    background: false, 
    progressDivider: 10, 
    progress: onDownloadFileProgress, 
    }) 

    yield download.promise; 

} 
+0

그것은 허용하지 않는다 <-> 당신은 그와 무슨 말을할까요 – Bergi

+0

수없는 이유는 무엇입니까? 차이가 있니? – delete

답변

10

한 가지 가능한 솔루션은 이미 언급 한 바와 같이, channels을 사용하는 것입니다. 여기

import { channel } from 'redux-saga' 
import { put, take } from 'redux-saga/effects' 

const downloadFileChannel = channel() 

export function* loadFile(id) { 
    ... 
    const download = RNFS.downloadFile({ 
    ... 
    // push `S_PROGRESS` action into channel on each progress event 
    progress: (progress) => downloadFileChannel.put({ 
     type: ACTIONS.S_PROGRESS, 
     progress, 
    }), 
    }) 
    ... 
} 

export function* watchDownloadFileChannel() { 
    while (true) { 
    const action = yield take(downloadFileChannel) 
    yield put(action) 
    } 
} 

아이디어는 우리가 RNFS.downloadFile에서 방출되는 각 progress 이벤트 채널에 S_PROGRESS 대처를 진행하는 것입니다 : 여기에 귀하의 경우에 작동합니다 예입니다.

while 루프 (watchDownloadFileChannel)에서 각 푸시 된 동작을 수신하는 다른 사가 기능을 시작해야합니다. 채널에서 조치가 취해지면 항상 yield put을 사용하여 redux-saga에게이 작업을 전달해야한다고 알립니다.

이 답변으로 도움이되기를 바랍니다.

+0

훌륭한 작품! 고마워요! – delete

+0

이것은 내 비슷한 문제에 대한 해결책처럼 보이지만 채널 버퍼 오버 플로우가 발생합니다. 'watchDownloadFileChannel'을 sagaMiddleware에 어떻게 연결 시켰습니까? – dougajmcdonald

1

저는 이번 주에 비슷한 상황에 처했습니다.

내 솔루션은 콜백 내부에서 디스패치를 ​​호출하고 결과를 전달하는 것이 었습니다. 다음 연결된 통화, 나는이 라운드 가지고 어떻게

function* uploadImageAttempt(action) { 
    const reader = new FileReader(); 

    reader.addEventListener('loadend', (e) => { 
    const loadedImage = reader.result; 
    yield put(Actions.uploadImage(loadedImage)); // this errors, yield is not allowed 
    }); 

    reader.readAsArrayBuffer(this.refs[fieldName].files[0]); 
} 

내 구성 요소에 readAsArrayBuffer()을 수행하여이었다

내가 처리 된 파일 업로드 때문에이처럼 내 사가 뭔가 처음에는 readAsArrayBuffer() 전화를하고 싶어 발송 기능 :

// in my file-uploader component 
handleFileUpload(e, fieldName) { 
    e.preventDefault(); 

    const reader = new FileReader(); 

    reader.addEventListener('loadend', (e) => { 
    const loadedImage = reader.result; 
    this.props.uploadFile(
     this.constructDataObject(), 
     this.refs[fieldName].files[0], 
     loadedImage 
    ); 
    }); 

    reader.readAsArrayBuffer(this.refs[fieldName].files[0]); 

} 

... 

const mapDispatchToProps = (dispatch) => { 
    return { 
    uploadFile: (data, file, loadedImage) => { 
     dispatch(Actions.uploadFile(data, file, loadedImage)) 
    } 
    } 
} 

희망 @ 알렉스 제안으로 channel를 사용하여 옆에

0

을하는 데 도움이, 하나는 call'redux-saga/effects'에서 사용하는 것도 고려해 볼 수 있습니다. call 효과는 Promise의 기능을가집니다.

import { call } from 'redux-saga/effects'; 
 

 
// ... 
 

 
yield call(download.promise);