cocos2dx-js CCBoot.js异步池cc.AsyncPool浅析

       首先通过一个问题的出现以及解决,来介绍cc.AsyncPool的实现。
       假设现在有个需求,就是一个页面里面要显示很多图片,而且这些图片是需要下载的。如果我们的实现方法是显示这个页面的时候,一次性请求并创建这些图片,这样做可能会出现当我们要显示这个页面的时候,会出现卡了几秒,然后图片一次性显示出来,显然这种体验是很差的。所以我们可能优化一下,当要显示这个页面时候先显示背景,然后创建去请求一个图片并创建成功后再去处理下一个。这里的实现模式就用cc.AsyncPool异步池来实现。
       通过上面的问题,我们先思考一下,我们实现的功能就是,别人传一堆数据过来,我们先取出一个数据,然后交给迭代器且处理,同时迭代器在处理完成的时候通知给我们,在通知给我们的时候,我们继续去下一个数据,当迭代器处理完成的数据等于原先总的数据的时候,就说明处理完成了。

所以我们实现一个异步池需要一下参数
      1、迭代处理的对象srcObj(上面例子的所有图片的远程地址列表)
      2、并行限制 limit,就是一次可以同时处理数量
      3、迭代器(上面例子的单个图片下载和创建控件流程)
      4、全部处理后的回调 onEnd
      5、上下文target(js的语法,修改函数的this指向)

      下面是cc.AsyncPool带注释的代码。

//+++++++++++++++++++++++++something about async begin+++++++++++++++++++++++++++++++
/**
 * Async Pool class, a helper of cc.async
 * @param {Object|Array} srcObj 迭代对象
 * @param {Number} limit the limit of parallel(并行) number  并行限制
 * @param {function} iterator 迭代器
 * @param {function} onEnd 全部执行后的回调
 * @param {object} target 迭代的上下文
 * @constructor
 */
// async 异步
// 异步池大概流程: 
// 记录总的需要处理的数量
// 取出一个数据,当前工作的数量加1,并执行迭代器 
//迭代器执行结束后,当前工作的数量减1,已完成的数据加1
// 如果已完成的数量等于需要处理的数据,表明全部处理完成,反之表面还没全部处理结束,尝试处理下一个数据
// 处理下一个数据时,如果当前工作的数据没有超过最大并发数,且待处理的池还有数据,取下个数据处理
  
cc.AsyncPool = function (srcObj, limit, iterator, onEnd, target) {
    var self = this;
    // 是否执行后全部结束的回调
    self._finished = false;
    // 需要处理的数据
    self._srcObj = srcObj;
   // 同时并发的最大数量
    self._limit = limit;
    // 等待处理的数据池
    self._pool = [];
    self._iterator = iterator;
    self._iteratorTarget = target;
    self._onEnd = onEnd;
    self._onEndTarget = target;
    self._results = srcObj instanceof Array ? [] : {};
    self._errors = srcObj instanceof Array ? [] : {};

    // 把srcObj已index-value的元素压入到数组_pool
    cc.each(srcObj, function (value, index) {
        self._pool.push({index: index, value: value});
    });

    // 总的数量
    self.size = self._pool.length;
    // 已经处理完成的数量,用于处理一个结束后判断是否全部处理完成用
    self.finishedSize = 0;
    // 正在工作的数量
    self._workingSize = 0;

    self._limit = self._limit || self.size;

    // 注入迭代器和其上下文
    self.onIterator = function (iterator, target) {
        self._iterator = iterator;
        self._iteratorTarget = target;
    };

    // 注入结束回调和其上下文(这个是不是没有用,和下面的onEnd冲突?)
    self.onEnd = function (endCb, endCbTarget) {
        self._onEnd = endCb;
        self._onEndTarget = endCbTarget;
    };

    // 处理单个
    self._handleItem = function () {
        var self = this;
        // 待处理池为空或者 当前工作的数量已经达到限制
        if (self._pool.length === 0 || self._workingSize >= self._limit)
            return;                                                         
        // 移除出一个
        var item = self._pool.shift();
        var value = item.value, index = item.index;
        // 正在处理的数量加1
        self._workingSize++;
        // 运行迭代器,参数为value,key,单个回调函数,异步池对象
        self._iterator.call(self._iteratorTarget, value, index,
            // 单个处理接口回调函数,参数为err和接口
            function (err, result) {
                // 结束回调已经执行过
                if (self._finished) {
                    return;
                }

                // 记录每个数据处理的错误或者结果
                if (err) {
                    self._errors[this.index] = err;
                }
                else {
                    self._results[this.index] = result;
                }
                // 已完成数量加1
                self.finishedSize++;
                // 正在运行数量减1
                self._workingSize--;
                // 完成数量等于总的数量(这里可以去掉这个变量)
                // 可以用当前正在工作的为空,且异步池没有对象了
                // if (self._workingSize === 0 && self._pool.length === 0)
                if (self.finishedSize === self.size) {
                    var errors = self._errors.length === 0 ? null : self._errors;
                    self.onEnd(errors, self._results);
                    return;
                }
                // 处理完一个后,处理下一个
                self._handleItem();
            }.bind(item),
            self);
    };
	
    // 异步池创建成功后,调用这个开始处理数据
    self.flow = function () {
        var self = this;
        if (self._pool.length === 0) {
            if (self._onEnd)
                self._onEnd.call(self._onEndTarget, null, []);
            return;
        }
        // 一次性并行多个
        for (var i = 0; i < self._limit; i++)
            self._handleItem();
    };
 
    // 全部处理完成回调
    self.onEnd = function(errors, results) {
        self._finished = true;
        if (self._onEnd) {
            var selector = self._onEnd;
            var target = self._onEndTarget;
            // 清空引用
            self._onEnd = null;
            self._onEndTarget = null;
            selector.call(target, errors, results);
        }
    };
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值