"use strict";
/**
    Promise的实现对象,接口基本与Jquery相同,不依赖JQuery的时候使用;
    
    Update Note:
        + 2014.10 :Created

    @module Promise
*/
_stDefine('deferred', function(st) {

    var priorityList = st.priorityList,
        sliceArgs = st.sliceArgs;

    /**
     * Deferred对象,非依赖jquery下加载使用
     * @class Deferred
     * @constructor
     */
    function Deferred() {
        var defer = this;
        defer.__state = 'pendding';
        defer.__resolvedCalls = priorityList();
        defer.__rejectedCalls = priorityList();
        defer.__alwaysCalls = priorityList();
    }

    function addCallbacks(defer, callbacks, state) {
        var status = defer.state(),
            list,
            len = callbacks.length,
            priority;

        if (len > 0) {
            callbacks = sliceArgs(callbacks);

            if (len > 1) {
                priority = callbacks[len - 1];

                if (priority === undefined || typeof priority === 'number')
                    callbacks.pop();
                else
                    priority = null;
            }

            if (status === state) {
                callbacks.forEach(function(callback) {
                    callback && callback.apply(null, defer.__result);
                })
            } else {
                list = defer['__' + state + 'Calls'];

                callbacks.forEach(function(callback) {
                    callback && list.add(callback, priority);
                })
            }
        }

        return defer;
    }

    function complete(defer, args, state) {
        defer.__state = state;

        var list = defer['__' + state + 'Calls'],
            fnCallback = function(callback) {
                callback.apply(defer, args);
            };

        list.each(fnCallback)

        defer.__alwaysCalls.each(fnCallback);
    }

    Deferred.prototype = {
        /**
         * 解决递延对象,并根据给定的参数调用任何完成的回调函数
         * @method resolve
         * @param  {object} result 解决传递的结果
         */
        resolve: function(result) {
            complete(this, arguments, 'resolved');
        },
        /**
         * 拒绝延迟对象,并根据给定的参数调用任何失败的回调函数。
         * @method reject
         * @param  {object} arg 拒绝传递的参数
         */
        reject: function(arg) {
            complete(this, arguments, 'rejected');
        },
        /**
         * 返回契约
         * @method promise
         */
        promise: function() {
            return this.__state === 'pendding' ? this : this.__result;
        },
        /**
         * 返回契约状态;
         *     1. pending: 未完成状态。 
         *     2. resolved: 解决状态。 
         *     3. rejected: 拒绝的状态。
         * @method state
         */
        state: function() {
            return this.__state;
        },
         /**
         * 当延迟成功时调用一个函数或者数组函数。
         * @method done
         * @param  {function|array} callback 回调函数或者数组函数
         */
        done: function(callback) {
            return addCallbacks(this, arguments, 'resolved');
        },
        /**
         * 当延迟失败时调用一个函数或者数组函数。
         * @method fail
         * @param  {function|array} callback 回调函数或者数组函数
         */
        fail: function(callback) {
            return addCallbacks(this, arguments, 'rejected');
        },
        /**
         * 当递延对象是解决或拒绝时被调用添加处理程序;
         * @method always
         * @param  {function|array} callback 回调函数或者数组函数
         */
        always: function() {
            return addCallbacks(this, arguments, 'always');
        },
        /**
         * 添加处理程序被调用时,递延对象得到解决或者拒绝;
         * @method then
         * @param  {function} doneCallback 成功回调函数
         * @param  {function} callback 失败回调函数或者数组函数
         * @param  {number} priority 权重;优先级
         */
        then: function(doneCallback, failCallback, priority) {
            doneCallback && this.done(doneCallback, priority);
            failCallback && this.fail(failCallback, priority);
            return this;
        }
    }

    return {
        Deferred: function() {
            return new Deferred();
        },
        /**
         * 捕获promise的方法,使用st.when调用;
         * @method when
         * @param  {object|args} result 单个判断对象或者一组(参数组)判断对象
         */
        when: function() {
            var deferList = sliceArgs(arguments),
                count = deferList.length,
                isResolve = true,
                num = 0,
                rets = new Array(count),
                isFinish,
                whenDefer = new Deferred();

            function process(i, result, state) {
                num++;
                if (isResolve && state === 'rejected')
                    isResolve = false;

                rets[i] = result;

                if (num === count) {
                    whenDefer[isResolve ? 'resolve' : 'reject'].apply(whenDefer, rets);
                    isFinish = true;
                }
            }

            deferList.forEach(function(defer, i) {
                if (defer instanceof Deferred) {
                    defer.always(function(result) {
                        process(i, result, this.state());
                    })
                } else
                    process(i, defer);
            })

            if (isFinish) {
                whenDefer.__result = rets;
            }
            return whenDefer;
        }
    };
})

    
Top