如何在回调中在 redux-saga 中 "yield put"?
How to "yield put" in redux-saga within a callback?
因为回调中不允许使用 "yield"-statement,我如何在回调中使用 redux-saga 的 "put" 功能?
我想收到以下回电:
function onDownloadFileProgress(progress) {
yield put({type: ACTIONS.S_PROGRESS, progress})
}
这是行不通的,并以 "unexpected token" 结束,因为 yield 在普通函数中是不允许的。否则我无法将回调作为“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;
}
正如您已经提到的,一种可能的解决方案是使用 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
.
发出的每个进度事件在频道上推送一个 S_PROGRESS
操作
我们还必须启动另一个 saga 函数,它在 while
循环 (watchDownloadFileChannel
) 中监听每个推送的动作。每次从频道采取行动时,我们使用正常的 yield put
告诉 redux-saga
应该调度此行动。
希望这个回答对您有所帮助。
我这周也遇到了类似的情况。
我的解决方案是在回调中调用调度并传递结果。
我正在处理文件上传,所以想做一个 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))
}
}
}
希望对您有所帮助
除了像@Alex 建议的那样使用 channel
之外,还可以考虑使用 'redux-saga/effects'
中的 call
。 call
效果取一个函数或 Promise
.
import { call } from 'redux-saga/effects';
// ...
yield call(download.promise);
这是最简单的方法:
import store from './store' // import redux store
store.dispatch(your action creator here)
因为回调中不允许使用 "yield"-statement,我如何在回调中使用 redux-saga 的 "put" 功能?
我想收到以下回电:
function onDownloadFileProgress(progress) {
yield put({type: ACTIONS.S_PROGRESS, progress})
}
这是行不通的,并以 "unexpected token" 结束,因为 yield 在普通函数中是不允许的。否则我无法将回调作为“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;
}
正如您已经提到的,一种可能的解决方案是使用 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
.
S_PROGRESS
操作
我们还必须启动另一个 saga 函数,它在 while
循环 (watchDownloadFileChannel
) 中监听每个推送的动作。每次从频道采取行动时,我们使用正常的 yield put
告诉 redux-saga
应该调度此行动。
希望这个回答对您有所帮助。
我这周也遇到了类似的情况。
我的解决方案是在回调中调用调度并传递结果。
我正在处理文件上传,所以想做一个 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))
}
}
}
希望对您有所帮助
除了像@Alex 建议的那样使用 channel
之外,还可以考虑使用 'redux-saga/effects'
中的 call
。 call
效果取一个函数或 Promise
.
import { call } from 'redux-saga/effects';
// ...
yield call(download.promise);
这是最简单的方法:
import store from './store' // import redux store
store.dispatch(your action creator here)