我正在使用redux-observable和socket.io并试图通过socket.emits来验证令牌,但是redux-observable说出了关于操作的事情。然后我尝试使用switchMaps,但我只在方法列表中进行了最后一次调度。我尝试了不同的运算符和方法,但它也没有用。我哪里错了?提前谢谢。
这是代码。首先,如果令牌为suc
到===
,我们会在服务器上发出令牌(例如它的suc
,就像成功一样),我发送带verifySuccess
的发送1}},否则为verifyError
。我已经测试了服务器端,以防可能存在问题,但事实并非如此。
前
export default function verify(action$) {
return action$.ofType(TOKEN_VERIFY_REQUEST)
.map(action => Observable.of(socket.emit('verify', { token: 'suc' })))
.mapTo(
Observable.fromEvent(socket, 'verifySuccess')
.mapTo({ type: TOKEN_VERIFY_SUCCESS })
)
.mapTo(
Observable.fromEvent(socket, 'verifyError')
.mapTo({ type: TOKEN_VERIFY_FAILURE })
)
}
回到
socket.on('verify', async (data) => {
console.log(`got verify with`.red)
console.log(data)
const msgs = {
suc: { msg: 'Received data' },
err: { msg: 'Error in request' }
}
console.log(`data.token is ${data.token}`)
if (data.token === 'suc') {
console.log(`sending success`)
socket.emit('verifySuccess', msgs.suc)
} else {
console.log(`sending error`)
socket.emit('verifyError', msgs.err)
}
})
答案 0 :(得分:1)
可能存在一些关于RxJS的基本误解,所以我会花一些时间来真正获得它的基础,或者考虑使用像redux-thunk这样的东西,如果你的异步需求并不比这更复杂。
所以这里有一些事情可以指导你:
map
正在返回一个Observable,这意味着你现在有一个Observable of Observables又称Observable<Observable>
,这几乎肯定不是你想要的。Observable.of(socket.emit('verify', { token: 'suc' })))
是什么意思,因为socket.emit()
返回套接字本身,所以你发出然后将动作映射到Socket本身的Observable?mapTo
用法也可能不是你想要的。第二个取消第一个,你再次创建一个Observable of Observable。所以你的史诗正在发出(并因此调度)一个Observables流,而不是动作,这就是为什么你从redux那里得到“动作必须是普通对象”的错误。我犹豫是否给你一个解决方案,但我会要求你试着真正理解它,而不仅仅是复制粘贴。也许退后一步,试着忘记你目前关于Rx如何运作并重新开始的信念?那么你可能会有“啊哈!”时刻:))
我猜你打算做这样的事情:
export default function tokenVerifyRequestEpic(action$) {
return action$.ofType(TOKEN_VERIFY_REQUEST)
.do(() => {
socket.emit('verify', { token: 'suc' }));
})
.mergeMap(() =>
Observable.race(
Observable.fromEvent(socket, 'verifySuccess')
.mapTo({ type: TOKEN_VERIFY_SUCCESS }),
Observable.fromEvent(socket, 'verifyError')
.mapTo({ type: TOKEN_VERIFY_FAILURE })
)
);
}
这是详细的内联评论:
export default function tokenVerifyRequestEpic(action$) {
// filter out all actions except TOKEN_VERIFY_REQUEST
return action$.ofType(TOKEN_VERIFY_REQUEST)
// perform the side effect of emitting the 'verify' message
.do(() => {
socket.emit('verify', { token: 'suc' }));
})
// One problem with this code is that it might not properly account for
// multiple concurrent TOKEN_VERIFY_REQUEST requests. e.g. How are those
// handled by the server? How should be they be handled in the UI?
// If it's not supposed to be possible, it might be useful to assert
// against that condition so that if it does accidentally happen you
// throw an error
.mergeMap(() =>
// Race between either a 'verifySuccess' or 'verifyError'
// This assumes one or the other will always happen, if not
// then you might want to add a timeout() or similar
Observable.race(
Observable.fromEvent(socket, 'verifySuccess')
.mapTo({ type: TOKEN_VERIFY_SUCCESS }),
Observable.fromEvent(socket, 'verifyError')
.mapTo({ type: TOKEN_VERIFY_FAILURE })
)
);
}