六狼论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

新浪微博账号登陆

只需一步,快速开始

搜索
查看: 29|回复: 0

JavaScript异步实现

[复制链接]

升级  82%

47

主题

47

主题

47

主题

秀才

Rank: 2

积分
173
 楼主| 发表于 2013-1-23 01:46:46 | 显示全部楼层 |阅读模式
Asynchronous method queue chaining in JavaScript

Thursday, May 6th, 2010
Chaining. It’s an extremely popular pattern these days in JavaScript. It’s easily achieved by continually returning a reference to the same object between linked methods. However one technique you don’t often see is queueing up a chain of methods, asynchronously, by which functions can be linked together independent of a callback. This discussion, of course, came from a late work night building the @anywhere JavaScript APIwith two other mad scientists, Russ D’Sa (@dsa) and Dan Webb (@danwrong).
Anyway, let’s have a look at some historical conventions and compare them to newer ones.
Imagine an iterator class that operated on arrays. It could look like this:
// no chainingvar o = new Iter(['a', 'b', 'c', 'd', 'e']);o.filter(function(letter) {  if (letter != 'c') { return letter; }});o.each(function(letter) {  append(letter);});// with chainingnew Iter(alphabet).filter(remove_letter_c).each(append);This is a simple because we’re working on a known existing object in memory (the alphabet array). However an easy way to spoil our soup is to make our methods continue to operate without existing objects. Like say, for example, a result set you had to make an async request to the server to get. Thus, imagine making this work:
ajax('/server/results.json').filter(remove_duplicates).append('div#results');In the grand scheme of things, the above example isn’t too far off from from currying (which it’s not). And to make another point, currying can often lead to bad coupling of code… which in its defense, is often the point as well. Some libraries even call this pattern binding… so… yeah.
Anyway, to the point, here is a basic Queue implementation that can be used as a tool to build your own asynchronous method chains.
function Queue() {  // store your callbacks  this._methods = [];  // keep a reference to your response  this._response = null;  // all queues start off unflushed  this._flushed = false;}Queue.prototype = {  // adds callbacks to your queue  add: function(fn) {    // if the queue had been flushed, return immediately    if (this._flushed) {      fn(this._response);    // otherwise push it on the queue    } else {      this._methods.push(fn);    }  },  flush: function(resp) {    // note: flush only ever happens once    if (this._flushed) {      return;    }    // store your response for subsequent calls after flush()    this._response = resp;    // mark that it's been flushed    this._flushed = true;    // shift 'em out and call 'em back    while (this._methods[0]) {      this._methods.shift()(resp);    }  }};With this code, you can put it straight to work for something useful, like say, a jQuery plugin that fetches content remotely and then appends the results to your selector input. For you plugin developers our there, it would look like this…
<script src="jquery.js"></script><script src="async-queue.js"></script><script>(function($) {  $.fn.fetch = function(url) {    var queue = new Queue;    this.each(function() {      var el = this;      queue.add(function(resp) {        $(el).html(resp);      });    });    $.ajax({      url: url,      dataType: 'html',      success: function(html) {        queue.flush(html);      }    });    return this;  };})(jQuery);</script>Then voila! You can make your DOM queries, fetch remote content, and continue your chain, asynchronously.
$("<div/>")  .fetch('/server/navigation.html')  .addClass('column')  .appendTo('#side');Here’s a brief example of showing off the example above. Point being, one can only imagine the possibilities you could do. Say for example, having multiple items in the queue waiting to operate on a response. Thus imagine this…
fetchTweet(url).linkify().filterBadWords().appendTo('#status');Your internals would look like this with the Queue.
function fetchTweet(url) {  this.queue = new Queue;  this.tweet = "";  var self = this;  ajax(url, function(resp) {    self.tweet = resp;    self.queue.flush(this);  });}fetchTweet.prototype = {  linkify: function() {    this.queue.add(function(self) {      self.tweet = self.tweet.replace(/\b@(\w{1,20}\b/g, '<a href="...">$1</a>');    });  return this;  },  filterBadWords: function() {    this.queue.add(function(self) {      self.tweet = self.tweet.replace(/\b(fuck|shit|piss)\b/g, "");    });  return this;  },  appendTo: function(selector) {    this.queue.add(function(self) {      $(self.tweet).appendTo(selector);    });  return this;  }};And with that, you can call it a night. Cheers.

 
原文:http://www.dustindiaz.com/async-method-queues/
您需要登录后才可以回帖 登录 | 立即注册 新浪微博账号登陆

本版积分规则

快速回复 返回顶部 返回列表