Promise让代码变得更人性化
曾经我一直在思考,为什么代码会比较难读。后来发现,我们平时要阅读的所有媒体:报纸、书、新闻,我们在阅读的时候,都是从上到下一直读下去的,然而,我们的在读代码的时候,经常要跳着去读,这种阅读方式其实是反人类的,如果我们能在读代码的时候,也可以从上往下一直读下去,那么,代码就会变得可读性提高很多。
对比JS中,callback是让我们跳来跳去读代码最大的罪魁祸首,它让我们的流程变得混乱,Promise正是为了解决这一问题而产生的。我们来对比一下这个过程
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
var render = function(data){ }; var getData = function(callback){ $.ajax({ success: function(){ callback(data); } }); }; var init = function(){ getData(function(data){ render(data); getData(function(data){ render(data); }); }); }; init(); |
使用Promise之后
1 2 3 4 5 6 7 8 9 10 11 12 |
var init = function(){ getData({ }).then(function(data){ render(data); return getData({}); }).then(function(data){ render(data); }); }; |
很明显看出,代码就变成线性的了,逻辑也变得更加清晰可读
Promise流程再优化
promse出来之后,大家都有很多的想法,在Promise之上再封装一层,使用异步流程更清晰可读。下面是Abstract-fence 2.0(开发中)的一种解决方案(规范)
Abstract-fence中,function会被分解为多个task
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
Model.task('getData', function(scope, next,{$, util}){ $.ajax({ success: function(data){ next(); } }); }); Model.task('render', ['getData'], function(scope){ var data = scope.data; // 使用data进行渲染 }); Model.task('init', [render].then(render)); Model.runWorkflow(init); |
其中, init是task render执行后再执行render, 而render任务又是由getData任务执行后再渲染组成,其中每个task的定义function的参数使用依赖注入传递,全局属性使用{}包裹
但是在使用Promise.all的过程中,遇到了一个Promise奇怪的问题
Array.prototype.then与Promise.all
很简单的一段代码
1 2 3 4 5 6 7 8 9 |
var p = new Promise(function(rs, rj){ setTimeout(rs, 1000); }); Promise.all([p]).then(function(){ console.log(2); }); console.log(1); |
毫无疑问,这段代码在浏览器运行会先打印1,然后再输出2 但如果在前面增加对then方法的定义,如下代码