RN离线缓存框架设计讲解

在这一节呢我们来学习如何设计一个React Native离线缓存框架

# 为什么要离线缓存呢?

    宏观上来说:

    * 提升用户体验: 我们要为用户提供流畅的APP操作体验,但我们无法保证所有用户的网络流畅度都是好的,所以我们需要离线缓存
      来提升用户体验
    * 节省流量:节省流量分两个层次:
        * 节省服务器流量
        * 节省用户手机的流量


    对于我们这款APP来说:

    * APP的数据来源在国外:咱们App的数据主要来自于Github,但Github的服务器在国外,所以在国内访问速度很不好,所以我们希望
      很不容易获取到的数据不能用一次就丢掉
    * 对数据实时性要求不高:https://github.com/trending的数据也不是实时更新的

# 离线缓存的策略

    * a: 优先从本地获取数据,如果数据过时或不存在则从服务器获取数据,数据返回后同时将数据同步到本地数据库
    * b: 优先从服务器获取数据,数据返回后同时将数据同步到本地数据库,如果网络故障则从本地获取数据
    * c: 同时从本地和服务器获取数据,如果本地数据库返回数据则先展示本地数据,等网络数据回来后在展示网络数据同时将数据
         同步到本地数据库

以上,是离线缓存的几种策略,我们就以a策略为例来讲解如何实现离线缓存

# 离线缓存的实现

    首先我们需要实现对数的存储:

# 数据存储

    saveData(url, data, callback) {
        if (!data || !url) return;
        AsyncStorage.setItem(url, JSON.stringify(this._wrapData(data)), callback)
    }

    上述代码我们实现了一个saveData方法,它接受一个url作为缓存数据的key,接受一个object的参数data作为保存的value,因为
    AsyncStorage是无法直接保存object的所以我们需要将其序列化成json

    a策略中提到了数据的有效期,所以我们要给缓存的数据加个时间戳:

    _wrapData(data){
        return {data: data, timestamp: new Date().getTime()}
    }

    注意:这里我们取的是本地时间作为的时间戳,本地时间存在被篡改的风险,如果条件允许可以取服务器的时间作为时间戳

# 获取本地数据

    fetchlocalData(url){
        return new Promise((resolve, reject) => {
            AsyncStorage.getItem(url, (error, result) => {
                if (!error) {
                    try {
                        resolve(JSON.parse(result))
                    } catch (e) {
                        reject(e)
                        console.error(e)
                    }
                } else {
                    reject(error)
                    console.error(error)
                }
            })
        })
    }

    AsyncStorage.getItem获取的数据是String类型的,以方便使用我们需要将其反序列成Object

# 获取网络数据

    fetchNetData(url) {
        return new Promise((resolve, reject) => {
            fetch(url)
                .then((response) => {
                    if (response.ok) {
                        return response.json()
                    }
                    throw new Error('Network response was not ok')
                })
                .then((responseData) => {
                    this.saveData(url, responseData)
                    resolve(responseData)
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    * 通过上述代码我们获取到网络数据,并对响应不成功的情况抛出了异常
    * 在获取到网络数据的同时我们将同步到了本地数据库

# 实现缓存策略

    按照a策略:优先从本地获取数据,如果数据过时或不存在则从服务器获取数据,我们需要这样设计我们的代码:

        * 我们优先获取本地数据
        * 如果数据存在且在有效期内,我们将数据返回
        * 否则我们获取网络数据

    fetchData(url){
        return new Promise((resolve, reject) => {
            this.fetchLocalData(url).then((wrapData) => {
                if (wrapData && DataStore.checkTimestampValid(wrapData.timestamp)) {
                    resolve(wrapData)
                } else {
                    this.fetchNetData(url)
                        .then((data) => {
                            resolve(this._wrapData(data))
                        })
                        .catch((error) => {
                            reject(error)
                        })
                }
            })
            .catch((error) => {
                this.fetchNetData(url)
                    .then((data) => {
                        resolve(this._wrapData(data))
                    })
                    .catch((error => {
                        reject(error)
                    }))
            })
        })
    }

    在上述代码中我们通过DataStore.checkTimestampValid来判断数据是否有效

    /*
        检查timestamp是否在有效期内
        true 不需要更新,false 需要更新
    */
    static checkTimestampValid(timestamp) {
        const currentDate = new Date()
        const targetDate = new Date()
        targetDate.setTime(timestamp)
        if (currentDate.getMonth() !== targetDate.getMonth()) {
            return false
        }
        if (currentDate.getDate() !== targetDate.getDate()) {
            return false
        }
        if (currentDate.getHours() - targetDate.getDate() > 4) {
            return false // 有效期4个小时
        }
        return true
    }
   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值