您的位置:首页 > Web前端 > JavaScript

异步JS

2015-07-26 19:29 591 查看
最近忙于工作项目,很久没有写博客了,然而博客还是得写,帮助很大。三言两语也好,以后尽量抽空多写写。欢迎指正交流。

第一次接触到异步的概念来自于ajax,即页面向服务端发请求,不等待返回结果而继续向后执行,当结果返回时执行回调,回调函数执行的时机是不确定的,取决于服务端何时返回结果。相对的,同步就是指一直等到结果返回后才继续向后执行。

我理解中,JS中实现异步的方式有两种:回调事件监听

一. 回调(callback)

最基本的回调方式,用一个简单的应用场景来阐述,假设我们要搜索数据,然后进行处理,最后显示结果,用异步来实现。在现实工作中这些函数会发出ajax请求并得到返回结果,现在我们就用setTimeout来简单模拟一下

function finder(records, callback) {
setTimeout(function() {
records.push(3, 4);
callback(records);
}, 1000);
}

function processer(records, callback) {
setTimeout(function() {
records.push(5, 6);
callback(records);
}, 1000);
}


finder([1, 2], function(records) {
processor(records, function(records) {
console.log(records);
});
});


我们调用finder函数,传入了一个回调函数,在这个回调函数中我们又调用processor函数,给它传入另一个回调函数。起个名字来引用回调函数可以使代码更易读

function onFinderDone(records) {
processor(records, onProcessorDone);
}

function onProcessorDone(records) {
console.log(records);
}

finder([1, 2], onFinderDone);


这种方式简单好理解,但其最大的一个缺点是你只能传入一个回调函数。

二. 事件监听(listener)

这块用到了jQuery的一些方法,不必太在意,重点在于阐述道理

首先我们需要两个对象,一个负责搜索数据,一个负责处理数据

var finder = {
run: function(records) {
var self = this;
setTimeout(function() {
records.push(3, 4);
self.trigger('done', [records]);
}, 1000);
}
};

var processor = {
run: function(records) {
var self = this;
setTimeout(function() {
records.push(5, 6);
self.trigger('done', [records]);
}, 1000);
}
};


与上例回调方式对比,我们把调用回调函数替换成了trigger方法,定义如下

var eventable = {
on: function(event, callback) {
$(this).on(event, callback);
},

trigger: function(event, args) {
$(this).trigger(event, args);
}
};


让我们的finder和processor对象获得事件监听、发布的能力

$.extend(finder, eventable);
$.extend(processor, eventable);


执行

finder.on('done', function(event, records) {
processor.run(records);
};

processor.on('done', function(event, records) {
console.log(records);
};

finder.run([1, 2]);


这种模式最大的优点在于你可以指定任意多个事件处理函数

原文中这一块过于依赖jQuery库,这里我参考了martinfowler的事件聚合(Event Aggregator),(原文http://martinfowler.com/eaaDev/EventAggregator.html或参考汤姆大叔的深入理解javascript系列),有兴趣的同学可以看看

function Event(name) {
var handlers = [];
this.getName = function() {
return name;
};
this.addHandler = function(handler) {
handlers.push(handler);
};
this.removeHandler = function(handler) {
for (var i = 0; i < handlers.length; i++ ) {
if (handlers[i] == handler) {
handlers.splice(i , 1);
break;
}
}
};
this.fire = function(eventArgs) {
for (var i = 0; i < handlers.length; i++ ) {
handlers[i](eventArgs);
}
};
}

function EventAggregator() {
var events = [];
function getEvent(eventName) {
return $.grep(events, function(event) {
return event.getName() == eventName;
})[0];
}
this.subscribe = function(eventName, handler) {
var event = getEvent(eventName);
if (!event) {
event = new Event(eventName);
events.push(event);
}
event.addHandler(handler);
};
this.publish = function(eventName, eventArgs) {
var event = getEvent(eventName);
if(!event) {
event = new Event(eventName);
events.push(event);
}
event.fire(eventArgs);
};
}


译自:http://sporto.github.io/blog/2012/12/09/callbacks-listeners-promises/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: