redux - redux saga yield call throw error TypeError: Cannot read property 'ready' of null
问题描述
我有一个应用程序,每次用户登录时都会加载“收藏夹”。数据是使用 localforage 从 IndexedDB 加载的。当应用程序重新启动时(窗口刷新后),它可以完美运行。当我注销并登录(root saga 任务运行)时,加载“收藏夹”数据的调用会引发错误:
TypeError:无法读取 null 的属性“就绪”
在步骤:
export function* handleRecoverFavorites() {
try {
const resp = yield call(localforage.getItem, 'favorites')
传奇代码提取:
export function* handleRecoverFavorites() {
try {
const resp = yield call(localforage.getItem, 'favorites')
if(resp) {
yield put(recoverFavorites(resp))
yield all(resp.map(symbol => put(getTickPricesSubscribe(symbol))));
}
} catch(err) {
let response={"errorDescr":"Error whilst recovering favorites: "+err}
yield put({ type: types.RESPONSE_ERR, response })
console.log(response.errorDescr)
}
}
function* runAtStartupSubscirptions(socket, streamSessionId) {
yield fork(send, {"command": "getBalance", "streamSessionId": streamSessionId }, socket );
yield fork(handleRecoverFavorites)
yield fork(handleRecoverCharts)
while(true) {
yield call(delay, STREAMING_PING_TIME)
yield call(send, {"command": "ping", "streamSessionId": streamSessionId }, socket );
}
}
function* handleRequests(socket) {
let streamSessionId = yield select(state => state.get("auth").get("streamSessionId"))
while(true) {
yield take(types.STREAMING_SOCKET_STATUS)
if(socket.readyState === 1)
yield fork(runAtStartupSubscirptions, socket, streamSessionId)
}
}
export function* handleStreamingConnection() {
let server = yield select(state => state.get("auth").get("server"))
const socket = yield call(createWebSocketConnection, server+"Stream" )
const socketChannel = yield call(createSocketChannel, socket, null)
const task = yield fork(handleRequests, socket)
let channelMsg;
do {
channelMsg = yield take(socketChannel)
if(channelMsg.socketResponse) {
const response = channelMsg.socketResponse;
switch (response.command) {
case "candle":
yield put({ type: types.GET_CANDLES_STREAMING, response })
break;
(...)
default:
console.log("unrequested data: "+response)
}
}
if(channelMsg.socketStatus) {
console.log(channelMsg)
yield put({ type: types.STREAMING_SOCKET_STATUS, channelMsg })
}
} while (channelMsg.socketStatus!=="Disconnected")
yield cancel(task)
}
export default function* rootSaga() {
while(true) {
// Wait for log-in
yield take(types.LOGIN_SUCCESS);
const handleStreamingtask = yield fork(handleStreamingConnection)
yield take([types.LOGOUT_REQUEST, types.RECONNECTING ])
yield cancel(handleStreamingtask)
const channelMsg={"socketStatus" : "Disconnected"}
yield put({ type: types.STREAMING_SOCKET_STATUS, channelMsg })
}
}
我将不胜感激任何建议。
我添加了 console.log 行以查看没有 saga 调用的结果:
export function* handleRecoverFavorites() {
try {
console.log(localforage.getItem('favorites'))
const resp = yield call(localforage.getItem, 'favorites')
每次 Promise 都会返回正确的值:
Promise {<pending>}
__proto__:Promise
[[PromiseStatus]]:"resolved"
[[PromiseValue]]:Array(1)
0:"CHFPLN"
length:1
解决方案
这就是我解决它的方法,而不是在“yield call”中直接调用 localforage 方法,而是将它包装到单独的类中:
export class LocalDataService {
getData = ( param ) => {
return localforage.getItem(param)
.then( result => result)
.catch( reason => reason)
}
}
export function* handleRecoverFavorites() {
try {
const api = new LocalDataService()
const resp = yield call( api.getData, 'favorites')
(...)
推荐阅读
- redis - 关于 Redis SETNX 和处理死锁的问题
- r - 更新 R Shiny 中的行后更新绘图
- flutter - 带有时间线的颤振设计
- python-3.x - 如何在 Python 的函数中包含“if”和“for”循环?
- php - 我在哪里使用 REST API 在 wordpress 数据库中发布和存储简单的 JSON 数据?
- typescript - 有没有办法为 Svelte 商店的更新定义泛型?
- python - 如何将c中的以下结构转换为python?
- flutter - 颤振如何在我的金额中输入美分
- angular - 具有 Angular 反应形式的依赖下拉列表
- reactjs - React如何为另一个组件返回div和变量值