js优化阿里云图片加载(一)

  1. 获取阿里云图片的过程
    服务器返回图片地址——请求服务器返回图片真实地址——获取图片

  2. 目前遇到的问题
    重复进行1的过程影响性能,实现图片加速加载。

  3. 在实际开发中的表现

    ·滑动列表时滑出去的item再次显示时会重复上述过程。
    ·反复查看某张图片。

  4. 实现过程
    4.1 已经完成的实现

let params = {pics: paths, process: 'image/resize,m_fixed,w_76,h_76'};

// network是封装的联网请求
let result = await network({
	type: "POST",
	url: '/mobile/oss/signForAppPic',
    param: params
     }, token);

let reSetResult = result.response ? result.response : result;
let realPaths = reSetResult.result;

       实现了在加载图片之前,从服务器获取真实的图片地址realPaths,然后再交给Image组件展示。发现真实的图片路径:https://gysy-picture.oss-cn-beijing.aliyuncs.com/app/x61tnmfx/BGQZ/ba112d3b-d41c-438a-ae88-002069a71aac.jpg?Expires=1543212261&OSSAccessKeyId=**********&Signature=*********&x-oss-process=image%2Fresize%2Cm_fixed%2Cw_100%2Ch_100
       有一个参数Expires是该图片在阿里云失效的时间秒数。因此,出现了一个解决思路就是:缓存真实的图片地址,每次加载图片时先看是否有缓存,缓存的图片是否在有效期内,如果是就直接加载图片;否的话,获取图片真实地址,再加载图片并缓存。

4.2 实现步骤

  • 图片地址的缓存,实现包括:初始化缓存对象、获取缓存中的值、设置缓存中的值。通过这几个方式实现了缓存的管理。(见4.3使用)

  • 有效期的判断,通过Expires与当前时间的对比。在已实现代码前添加判断,添加后:

let realPaths;

if (isValid(cacheRealPaths) && this.state ) {
	realPaths = cacheRealPaths;
   	return;
}

let params = {pics: paths, process: 'image/resize,m_fixed,w_76,h_76'};
// network是封装的联网请求,可以根据实际的联网请求进行更改
let result = await network({
	type: "POST",
	url: '/mobile/oss/signForAppPic',
    param: params}, token);
let reSetResult = result.response ? result.response : result;

realPaths = reSetResult.result;

4.3 使用
       将使用的方法封装到了ALiYunImageCache.js中。

/**
 * 初始化缓存对象
 * @param arr
 * @returns {*}
 */
let initCache = (arr) => {

    if (arr) {
        return new Array(arr.length);
    } else {
        return null;
    }

};

/**
 * 获取缓存中的值
 * @param arr
 * @param index
 * @returns {*}
 */
let getCache = (arr, index) => {

    if (arr && arr.length > index) {
        return arr[index];
    } else {
        return arr;
    }

};

/**
 * 设置缓存中的值
 * @param arr
 * @param index
 * @param newItem
 * @returns {*}
 */
let setCache = (arr, index, newItem) => {
    if (arr && arr.length > index) {
        return arr[index] = newItem;
    } else {
        return newItem;
    }

};

/**
 * 验证缓存是否有效
 * @param cacheRealPaths
 * @returns {boolean}
 */
let isValid = (cacheRealPaths) => {
    if (cacheRealPaths && cacheRealPaths.length > 0) {
        let start = cacheRealPaths[0].indexOf('=') + 1;
        let end = cacheRealPaths[0].indexOf('&');
        let validTime = parseInt(cacheRealPaths[0].substring(start, end));
        let curTime = (new Date().getTime()) / 1000;
        if (validTime > curTime) {
            return true;
        }
    }
    return false;
};


module.exports = {initCache, getCache, setCache, isValid};
  • 初始化
           构造方法里和缓存对象变化时,使用其中的initCache(arr)方法,返回保存的变量。arr:缓存的对象是列表时,传入对应的数组;否则传服务器返回的图片地址。
  • 获取缓存对象
           给展示图片的组件使用,getCache(arr, index)。arr是第一步保存的变量,index:缓存的对象是数组时,传入list中对应的索引;否则不传。
  • 更新缓存
           使用setCach(arr, index, newItem)。arr是第一步保存的变量,index:缓存的对象是数组时,传入list中对应的索引;否则传null。newItem:传新需要缓存的图片地址。
  1. 例子(一个列表每个item包含多张图片)
export default class demo extends Component {

    constructor(props) {
        super(props);

        // 初始化
        this.cacheRealPaths = initCache(props.connectListData);

    }

    componentWillReceiveProps(props) {
        if (props.dataList !== this.props.dataList) {
	    	// 所对应list数据变化时,重新初始化缓存
            this.cacheRealPaths = initCache(props.dataList);
        }
    };

    renderItem = ({item, index}) => (
        <DemoItem
            index={index}
            data={item}
            cacheRealPaths={getCache(this.cacheRealPaths, index)}   				// 获取该index对应的缓存 
            updateCacheRealPath={(index, arr) => setCache(this.cacheRealPaths, index, arr)}	// 设置index对应的缓存 
        />
    );

    render() {
        return (
            <View>
                <FlatList
                    data={this.props.dataList}
                    keyExtractor={(item) => this.keyExtractor(item)}
                    renderItem={this.renderItem}
                />
            </View>

        );
    }
}

class DemoItem extends Component {

    render() {
        return (
            <View>
                <PhotoHorizontalScroll 
                    paths={this.props.data.pictures}
                    cacheRealPaths={this.props.cacheRealPaths}
                    updateCacheRealPath={(arr) => this.props.updateCacheRealPath(this.props.index, arr)}
            </View>
        )
    }
}

export default class PhotoHorizontalScroll extends Component {
    // 构造
    constructor(props) {
        super(props);

        this.state = {
            paths: []
        };

        ...

        this.newPaths = null;
    }

    ...

    showPictures = async (paths, cacheRealPaths) => {

        this.newPaths = paths;
        if (paths && paths.length > 0) {

            // 添加有效判断
            if (isValid(cacheRealPaths) && this.state ) {
                this.setState({paths: cacheRealPaths});
                return;
            }

            let userInfo = await getUserInfo();
            let token = '';
            if (userInfo) {
                token = userInfo.access_token;
            }

            let params = {pics: paths, process: 'image/resize,m_fixed,w_76,h_76'};
            let result = await network({
                type: "POST",
                url: '/mobile/oss/signForAppPic',
                param: params
            }, token);

            let reSetResult = result.response ? result.response : result;

	    // 通知父组件更新缓存
            this.props.updateCacheRealPath && this.props.updateCacheRealPath(reSetResult.result);

            if (this.newPaths === paths && this.state) {
                this.setState({
                    paths: reSetResult.result
                })
            }
        }
        else {

            if (this.state) {
                this.setState({
                    paths: []
                })
            }
        }
    };

    ...

    render() {
        return (
            <ScrollView style={[this.props.style]}
                        horizontal={true}
                        showsHorizontalScrollIndicator={false}
            >
                <View style={{flexDirection: 'row'}}>
                    {this.renderImages(this.state.paths)}
                </View>
            </ScrollView>
        );
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值