【问题标题】:AsyncStorage behaviour异步存储行为
【发布时间】:2018-05-03 07:56:55
【问题描述】:

我遇到了 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);
        });
    }

如您所见,我根据文档将callback 函数传递给getItem(),它基本上告诉我用户之前是否已登录并且此后未注销(即令牌仍然存在在某处的设备/应用程序中)。 这段代码第一次成功,取回了我通过reducer存储的旧token:

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 也总是无法检索到数据。

我也尝试了AsyncStorage 调用的变体,即使用await.then 加上.catch,但它们都导致相同的结果。

我的问题是:

  1. 在失败的情况下,我的印象是getItem() 仍然会调用我传递的回调函数,因为参数列表中有一个error。但是,我的 console.log 从未在上述情况下运行。我在期待一些不该出现的东西吗?

  2. 为什么它只会从第二次开始就一直失败?是否存在多次在同一个键上调用setItem() 而不删除它会导致存储失败的情况? (我确信第一次尝试是成功的,因为我打印了从异步存储中检索到的令牌)

  3. 这与我从 Expo 加载我的应用程序并使用 CRNA 初始化应用程序这一事实有关吗?这会以某种方式使 asyncStorage 持久性质量有所不同吗?

提前致谢! :)

编辑:经过进一步检查,似乎停止打包程序并再次运行它似乎允许应用程序再次成功检索旧令牌,但如果我再次刷新应用程序,在编辑代码后,getItem() 将再次失败。那么这与 Expo 和持久存储有关吗?

【问题讨论】:

    标签: javascript reactjs asynchronous react-native expo


    【解决方案1】:

    reducer 必须没有副作用,因为它是一个纯函数。

    docs中所述

    它们必须是纯函数——对于给定输入返回完全相同输出的函数。它们还应该没有副作用。

    副作用 - 当过程从其范围之外更改变量时

    更好的方法是使用redux-saga这就像你的副作用模型的单独线程

    【讨论】:

    • 啊,我明白了,一定是错过了那个!多谢! :)
    【解决方案2】:

    感谢我的一位更有经验的程序员朋友,现在问题已经解决了。 原来我的错误是我把AsyncStorage.setItem() 调用放在reducer 中,他说它本质上是deterministic。 在调度之前,我将调用移至该类的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();
      }
    }
    

    但我的问题仍然是persists(请原谅双关语),“为什么这种简单的修改有效?我在这里理解reducersdispatchers 的机制错了吗?”

    另外,deterministicAsync 调用不兼容意味着什么?

    如果有人可以向我解释这个概念,那就太棒了! :D

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 1970-01-01
      • 2016-04-13
      • 2020-11-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多