2017-03-26 6 views
6

コールバック内で「yield」文が使用できないため、どのようにredux-sagaの「put」機能をコールバック内で使用できますか?コールバック内でredux-sagaに "put"をもたらす方法は?

私は、次のコールバックを持っているしたいと思います:

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

歩留まりがプレーン機能で許可されていませんので、これは、作業と「予期しないトークン」で終わるされていません。さもなければ私は "機能*"としてコールバックを渡すことができません、それは歩留まりを可能にします。ここで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

私は今週同様の状況に陥りました。

私の解決方法は、コールバック内でディスパッチを呼び出して結果を渡すことでした。

私はこのような何か最初は私の武勇伝に、readAsArrayBuffer()コールをやってみたかったファイルのアップロードを処理していた。その後、接続を呼び出して、これは私のコンポーネントでreadAsArrayBuffer()を行うことによりだっラウンド私が得た方法

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]); 
} 

ディスパッチ関数:

// 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)) 
    } 
    } 
} 

希望@Alexが示唆するようchannelを使用して横に

0

を助け、 call'redux-saga/effects'から使用することも考えられます。 callエフェクトには、Promiseという機能があります。

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

 
// ... 
 

 
yield call(download.promise);

関連する問題