如何"屈服放置"在回调中的redux-saga?

时间:2017-03-26 17:04:52

标签: javascript ecmascript-6 redux yield redux-saga

因为" yield" -statement在回调中是不允许的,我如何使用" put"回调中的redux-saga的特征是什么?

我想要进行以下回调:

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

这不起作用并最终出现在"意外令牌",因为普通功能中不允许 yield 。否则,我无法通过回调作为" 函数* ",这将允许收益。 ES6似乎在这里打破了。

我已经读到redux-saga提供了一些名为" 频道"的功能,但说实话,我没有得到它。我已多次阅读过有关这些频道和示例代码的内容,但在所有示例中,他们都解决了非常困难和不同的问题,而不是我的简单案例,并且在一天结束时我已经到了那里

有人可以告诉我如何处理这个问题的解决方案吗?

整个背景:

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;

}

4 个答案:

答案 0 :(得分:25)

正如您已经提到的,一种可能的解决方案是使用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)
  }
}

这里的想法是,我们将针对从S_PROGRESS发出的每个进度事件在频道上推送RNFS.downloadFile操作。

我们还必须启动另一个saga函数,该函数正在while循环(watchDownloadFileChannel)中监听每个推送操作。每次从渠道采取操作时,我们都会使用正常的yield put告诉redux-saga应该调度此操作。

我希望这个答案可以帮到你。

答案 1 :(得分:1)

本周我陷入了类似的境地。

我的解决方案是在回调中调用一个调度并传递结果。

我正在处理文件上传,所以想要进行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]);
}

我如何解决这个问题是通过在我的组件中执行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))
    }
  }
}

希望有所帮助

答案 2 :(得分:0)

除了使用channel作为@Alex建议之外,还可以考虑使用call中的'redux-saga/effects'call效果采用函数或Promise

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

// ...

yield call(download.promise);

答案 3 :(得分:0)

这是最简单的方法:

import store from './store' // import redux store
store.dispatch(your action creator here)