Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

有时获取不到刚存的数据 #270

Open
yesgit opened this issue Feb 22, 2024 · 2 comments
Open

有时获取不到刚存的数据 #270

yesgit opened this issue Feb 22, 2024 · 2 comments

Comments

@yesgit
Copy link

yesgit commented Feb 22, 2024

场景是登录成功后保存token,然后用token去获取用户其他数据,但是后续拿到的token总是空的,多次重新登录都不行,除非重新安装应用。

测试环境从来没遇到,生产上Android、iPhone、iPad都遇到过,看代码没看出问题,很难复现。

依赖:

    "react-native": "0.72.3",
    "react-native-storage": "^1.0.1",
    "@react-native-async-storage/async-storage": "^1.19.2",

代码:

//import
import AsyncStorage from '@react-native-async-storage/async-storage';
import Storage from 'react-native-storage';

//storage声明和配置
var storage = new Storage({
  size: 1000,
  storageBackend: AsyncStorage,
  defaultExpires: null,
  enableCache: true,
  sync: {}
})
global.storage = storage;
//写入
export function setStorage(keyId,data,i){
  if(i == undefined){
    i = null
  }
  let key = keyId;
  let id = undefined;
  if(keyId.indexOf('-') != -1){
    let parts = keyId.split('-');
    key = parts[0];
    id = parts[1];
  }
  storage.save({
      key: key, 
      data: data,
      expires: i,
      id: id
    });
}
//读取
export function getStorage(keyId,callback){
  let key = keyId;
  let id = undefined;
  if(keyId.indexOf('-') != -1){
    let parts = keyId.split('-');
    key = parts[0];
    id = parts[1];
  }
  if(!callback)
  return new Promise((resolev, reject)=>{
    storage.load({
    key: key,
    id: id,
    autoSync: true,
    syncInBackground: true,
    syncParams: {
      extraFetchOptions: {
      },
      someFlag: true,
    },
    }).then(ret => {
      resolev(ret);
    }).catch(async err => {
    switch (err.name) {
        case 'NotFoundError':
          reject(new Error('Not found ' + key));
          // TODO;
          break;
        case 'ExpiredError':
           //这里有一段重新获取和写入Token的逻辑
            break;
          }
          reject(new Error(key + ' is expired'));
            break;
        default:
            reject(new Error('Not found ' + key));
    }
  })
  });
  storage.load({
    key: key,
    id: id,
    autoSync: true,
    syncInBackground: true,
    syncParams: {
      extraFetchOptions: {
      },
      someFlag: true,
    },
    }).then(ret => {
      callback(ret)
    }).catch(async err => {
    switch (err.name) {
        case 'NotFoundError':
          callback(null)
          break;
        case 'ExpiredError':
          //这里有一段重新获取和写入Token的逻辑
            break;
        default:
            callback(null);
    }
  })
}

//异步读取函数
export const getTempInfo = async (key) => {
  let result = '';
  try {
    result = await getStorage(key);
  } catch ( err ) {
    console.log(err.message);
    return '';
  }
  return result;
}

//登录成功的代码节选
if (succ && succ.code === '0000') {
    storage.remove({key:'token'});//移除旧token
    setStorage('token', succ.content.token, tokenTime); //写入新token,并设置过期时间
    getTempInfo("token").then((token) => { //这里获取token,但是获取为空
    succallback();
} else {
    errcallback(succ.message);
}

现在怀疑的地方:

  1. 达到了Android 6mb上限。但是ios也有这个问题,所以,至少不完全是这个原因。针对性测试也未复现。
  2. 达到了1000条限制。按理说达到限制后,循环使用,会把最旧的踢掉,不应该出现这个问题。针对性测试也未复现。
  3. enableCache:true 启用内存缓存导致的。会不会是缓存刷新问题?这个暂时没有排除。但接连多个请求都没有拿到token。
  4. autoSync: true, 导致的,没有同步,却启用了同步。这个不知道会不会有问题。测试环境似乎从来没出现问题。
  5. save后立即load导致的。因为save是异步的,所以可能load不到。这个也不太像,接连多个请求都拿不到,后续请求也拿不到。

有谁遇到或知道这个问题怎么解决吗?或有什么主意吗?辛苦帮忙回复,不胜感谢!!!

@codering
Copy link

codering commented Feb 22, 2024

这么简单的场景,我觉得应该是你的代码逻辑问题。
这个库每个操作都是异步的,你最好把每一步用 Promise then 连起来(或者 async await), 才能确保是顺序执行的。

我提出的改进建议:

  • 让 setStorage 返回Promise
export function setStorage(keyId,data,i){
 ...
 ...
 return storage.save({
      key: key, 
      data: data,
      expires: i,
      id: id
    });
}
  • 改进你写的代码节选
if (succ && succ.code === '0000') {
    storage.remove({key:'token'}).then(() => {
           setStorage('token', succ.content.token, tokenTime).then(() => {
                 getTempInfo("token").then((token) => { 
                    //这里获取token
                 }
                 succallback();
          })
    })
} else {
    errcallback(succ.message);
}
// 你也可以通 async await 语法,可以看起来更简洁
  • 如果你没有用同步功能,最好把它关闭

@yesgit
Copy link
Author

yesgit commented Feb 22, 2024

这么简单的场景,我觉得应该是你的代码逻辑问题。 这个库每个操作都是异步的,你最好把每一步用 Promise then 连起来(或者 async await), 才能确保是顺序执行的。

我提出的改进建议:

  • 让 setStorage 返回Promise
export function setStorage(keyId,data,i){
 ...
 ...
 return storage.save({
      key: key, 
      data: data,
      expires: i,
      id: id
    });
}
  • 改进你写的代码节选
if (succ && succ.code === '0000') {
    storage.remove({key:'token'}).then(() => {
           setStorage('token', succ.content.token, tokenTime).then(() => {
                 getTempInfo("token").then((token) => { 
                    //这里获取token
                 }
                 succallback();
          })
    })
} else {
    errcallback(succ.message);
}
// 你也可以通 async await 语法,可以看起来更简洁
  • 如果你没有用同步功能,最好把它关闭

非常感谢您的回复!!!
核心逻辑应该就是用then把异步变同步,我试一下,不知道大家都是这么写的吗?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants