转载

是时候把 Promise 写成一般的函数调用了

懒是一个程序员的好习惯,没错就是这样。

问题

假设使用 JQuery 来写一个 Promise ,有以下 2 个条件:

ajax
$.ajax

那么这个方法大概是这样的:

var getData = function (data1, data2){
    var defer = $.Deferred();
    $.get('http://xxx.xxx.xxx?data1=' + data1 + '&data2=' + data2)
        .then(function(result){
            defer.resolve(result);
        })
    return defer.promise();
}
getData().then(function(result){
    console.log(result)
})

感觉还是挺简洁干净的,但对于每天要写 10 多个 ajax 的我来说,这在我脑里就是这样:

while(true){
    var defer = $.Deferred();
    defer.resolve(result);
    return defer.promise();
}

能不能把这 3 行给干掉啊,这样我就能少些 n * 3 行代码了。我也不想显示的控制返回,需要我脑子参与的应该就仅仅是写个逻辑。

解决

让函数返回函数,内层函数声明 Promise 函数,并在最后返回该 Promise 对象。

需要执行的函数以参数的形式传入到外层函数,在内层函数中进行调用,将 Promise 修改状态的两个函数 resolvereject 以参数形式传入以参数形式传入的函数 func

感觉有点绕,直接上代码吧。

首先不考虑执行的函数需要传递传参的情况,这种情况比较简单。

function q(func){
    return function(){
        var defer = $.Deferred();
        func && func(defer.resolve, defer.reject);
        return defer.promise();
    }
}

然后 getData 就变成这样了:

var getData = q(function (resolve, reject){
    $.get('http://xxx.xxx.xxx')
        .then(function(result){
            resolve(result);
        })
})
getData().then(function(result){
    console.log(result)
})

是不是有一种酣畅淋漓的感觉,光写主要的代码逻辑就好了,函数返回的就是 Promise

接下来考虑到 getData 可能需要传入参数,就如同开头说的那样,而且我们要实现的是通用的函数,所以我们不知道实际传入的参数的个数,但是实现起来需要用到 applyarguments 这两个在 js 中不太被了解的东西。

思考后,撸出了这样的代码,供大家参考:

function q(func){
    return function(){
        var args = Array.prototype.slice.call(arguments);
        var defer = $.Deferred();
        args.push(defer.resolve, defer.reject);
        func && func.apply(undefined, args);
        return defer.promise();
    }
}

那么 getData 就可以这样了:

var getData = q(function (data1, data2, resolve, reject){
    $.get('http://xxx.xxx.xxx?data1=' + data1 + '&data2=' + data2)
        .then(function(result){
            resolve(result);
        })
})
getData().then(function(result){
    console.log(result);
})

对于其他的不同实现的 Promise 比如说 $qQ 、原生实现的 Promise 也是一样的,

原生的 Promise

function q(func){
    return function(){
        var args = Array.prototype.slice.call(arguments);
        return new Promise(function(resolve, reject) {
            args.push(resolve, reject);
            func && func.apply(undefined, args);
        });
    }
}

angular 中的 $q

function q(func){
    return function(){
        var args = Array.prototype.slice.call(arguments);
        var defer = $q.defer();
        args.push(defer.resolve, defer.reject);
        func && func.apply(undefined, args);
        return defer.promise;
    }
}

无论多少个参数都没用问题,突然感觉如沐春风啊,不多说了我要把剩下来的时间拿去睡觉拿去 happy 了。

最后强调一遍: 懒是一个程序员的好习惯,没错就是这样。

原文  https://segmentfault.com/a/1190000008092611
正文到此结束
Loading...