blogs
blogs copied to clipboard
Promiss / async / awiat
本文将梳理描述一些 异步程序开发方面的流派。 也不见得是异步的,回调很多的程序来开发的话也是这一套
- 回调函数
- 事件监听
- $.Deferred
- Promiss
- async / awiat
- continuation.js
- Generator
回调函数 callback
function fn1(callback) {
setTimeout(function(){
callback && callback();
}, 100);
}
fn1(function(){ alert(); });
回调函数的优点是 简单、容易理解和部署。
缺点是不利于代码的阅读和维护,各个部分之间 高度耦合,流程会很混乱,而且每个任务只能指定一个回调函数。 比如 fn1(fn2(fn3)) 既不好看,改为 fn3(fn2) 也不见得很方便(比如未封装成方法的时候),绑两个回调比较麻烦等问题。
未封装时候写回调,形象可以戏称未“回调金字塔”,尖角向右的那个样子
事件监听
我们就用 jquery 的 on + trigger 也是非常漂亮的。
function fn1() {
setTimeout(function(){
$('.my-list').triggle('done')
}, 100);
}
$('.my-list').on('done', f2).on('done', f3);
事件驱动模式,任务的执行不取决于代码的顺序,而取决于某个事件是否发生。
优点是比较容易理解,可以绑定多个事件,每个事件可以指定多个回调函数,而且可以去耦合,有利于实现模块化。
缺点是整个程序都要变成事件驱动型,运行流程会变得很 不清晰。
其实你把它叫做“观察者模式”或者“订阅发布模式”也是可以的,只是把 $('x') 改成了别的。 比如 var Event = new Vue(); Event.$on('xx'); Event.$emit('xx') 这种事件调度器。 原生如何写观察者模式呢,可见 这里
$.Deferred
当时初次接触到 $.Deferred 时惊叹不已,这世间竟还有如此骚的操作。
$.ajax("test.html")
.done(function(){ alert('哈哈,成功了!'); })
.done(function(){ alert('我还能再运行一次'); })
.fail(function(){ alert('出错啦!'); });
// 或者多个 ajax 一起玩耍
$.when($.ajax('test1.html'), $.ajax('test2.html'))
.done(function(){ alert('哈哈,成功了!'); })
基于 $.Deferred 自定义的异步就按下面这样写
var dtd = $.Deferred();
function wait(dtd){
setTimeout(function() {
dtd.resolve('finish');
}, 500);
return dtd;
};
$.when(wait(dtd))
.done(function(text){ alert(text); })
.done(function(text){ alert(text); })
jQuery 源码:https://github.com/jquery/jquery/blob/master/src/deferred.js
原理大致为,
Promise
function fn1(){
return new Promise(function(resolve, reject){
setTimeout(function(){
alert('');
}, 500);
})
}
ES6 标准化了的 Promise 相比 $.Deferred 有什么不一样呢,其实 var Promise = $.post 这样来看还真没什么不同。
兼容代码:https://www.promisejs.org/polyfills/promise-7.0.4.js 虽然不是源码,但可以大致一窥 Promise 的实现原理。
async / awiat
continuation.js
GitHub:https://github.com/BYVoid/continuation
其实还不理解它的原理,但它确实做到了,有兴趣的可以研究一番,在此只作拓展阅读了。
function textProcessing(ret) {
fs.readFile('somefile.txt', 'utf-8', cont(err, contents));
if (err) return ret(err);
contents = contents.toUpperCase();
fs.readFile('somefile2.txt', 'utf-8', cont(err, contents2));
if (err) return ret(err);
contents += contents2;
fs.writeFile('somefile_concat_uppercase.txt', contents, cont(err));
if (err) return ret(err);
ret(null, contents);
}
textProcessing(cont(err, contents));
if (err) console.error(err);
Generator
http://www.ruanyifeng.com/blog/2015/04/generator.html