Javascript 异步存储行为
我遇到了一个奇怪的Javascript 异步存储行为,javascript,reactjs,asynchronous,react-native,expo,Javascript,Reactjs,Asynchronous,React Native,Expo,我遇到了一个奇怪的AsyncStorage行为,我无法理解,如果有人能向我解释幕后发生了什么(即失败案例和原因),我将不胜感激 以下是我正在编写的代码: componentDidMount() { let _this = this; AsyncStorage.getItem('token', (err, data) => { setTimeout(() => { if(data !== null
AsyncStorage
行为,我无法理解,如果有人能向我解释幕后发生了什么(即失败案例和原因),我将不胜感激
以下是我正在编写的代码:
componentDidMount() {
let _this = this;
AsyncStorage.getItem('token', (err, data) => {
setTimeout(() => {
if(data !== null){
this.setState({isReady: true, isLoggedIn: true});
store.dispatch({type: t.LOGGED_IN, token: data});
}
else{
this.setState({isReady: true, isLoggedIn: false})
store.dispatch({type: t.LOGGED_OUT});
}
}, 3000)
console.log(err);
});
}
如您所见,我正在根据文档向getItem()
传递一个callback
函数,它基本上告诉我用户之前是否登录过,之后是否没有注销(即令牌仍然存在于设备/应用程序的某处)。
这段代码第一次成功,检索了我通过reducer存储的旧令牌:
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
AsyncStorage.setItem('token', action.token);
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
AsyncStorage.removeItem('token');
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
但是,在我第二次重新加载应用程序时,AsyncStorage
将始终无法检索数据,即使在我多次尝试登录之后也是如此
我也尝试了不同的异步存储
调用,即使用等待
,。然后
加上。捕获
,但它们都会导致相同的结果
我的问题是:
getItem()
仍将调用我传递的回调函数,因为参数列表上有一个错误。但是,在上述情况下,我的console.log从未运行过。我是不是在期待一些我不该在这里的事情
setItem()
,而不删除它会导致存储失败?(我确信第一次尝试是成功的,因为我打印了从异步存储中检索到的令牌)编辑:进一步检查后,停止打包程序并再次运行似乎允许应用程序再次成功检索旧令牌,但如果我在编辑代码后再次刷新应用程序,
getItem()
将再次失败。这是Expo和持久存储的问题吗?多亏了我的一位更有经验的程序员朋友,现在这个问题已经解决了。
原来我的错误是我把AsyncStorage.setItem()
调用放在了reducer中,他说reducer本质上是确定性的。
在分派之前,我将调用移到了该类的actions.js
,它就可以工作了
所以不是
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
AsyncStorage.setItem('token', action.token);
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
AsyncStorage.removeItem('token');
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
是的
export default function authReducer(state = initialState, action)
{
switch (action.type) {
case t.LOGGED_IN:{
return Object.assign({}, state, { isLoggedIn: true, token: action.token });
}
case t.LOGGED_OUT:{
return Object.assign({}, state, {isLoggedIn: false, token: null});
}
default:
return state;
}
}
再加上这个
export function login(data, successCB, errorCB) {
return (dispatch) => {
api.login(data, function (success, data, error) {
if (success && data.exists) {
AsyncStorage.setItem('token', data.token); //NOTE THIS
dispatch({type: t.LOGGED_IN, token: data.token});
successCB(data);
}else if (error) errorCB(error)
});
};
}
export function signOut(successCB, errorCB){
return (dispatch) => {
AsyncStorage.removeItem('token'); //NOTE THIS
dispatch({type: t.LOGGED_OUT});
successCB();
}
}
但是我的问题仍然存在(请原谅我的双关语),“为什么简单的修改有效?我理解了减缩器和调度器的机制吗?”
另外,确定性的意味着什么,与异步调用的不兼容性有什么关系
如果有人能向我解释这个概念,那就太棒了D还原剂必须无副作用,因为它是一种纯功能
如报告中所述
它们必须是纯函数——对于给定输入返回完全相同的输出的函数。它们也应该没有副作用
副作用-当程序从其范围外更改变量时
一个更好的方法是使用,这就像一个单独的线程为您的副作用模型。啊,我明白了,一定错过了那个!谢谢你(堆!)