Promise, Future, Dojo…
Dojo上一个普通的Ajax调用:
var xhrHandler = dojo.xhrGet({url:this.url, handleAs:"json-comment-optional", content:serverQuery}); xhrHandler.addCallback(dojo.hitch(this, function(data){ this._xhrFetchHandler(data, request, fetchHandler, errorHandler); })); xhrHandler.addErrback(function(error){ errorHandler(error, request); });
addCallback时,如果deferred已经完成,则传入的function被立刻执行。所以如果上面的xhrGet很快执行完成,则加入的callback也会被执行(这个时候消息队列为空),如同代码顺序执行。如果xhrGet较长时间完成,则加入的callback会有异步运行的效果。
上面的代码感觉很奇特,有种时空的错觉。如果dojo.xhrGet(..).addCallback(…).addCallback(…)则好点。
这个东西叫Promise,在CommonJS有单独的列出来,写法可以这样requestData(“foo.bar.com”).then(…).then(),看上去直观了很多。新的Dojo.js语法里面也有这个东西,不算新,只是我对Promise这个词很感兴趣,还有Future。
当命名一个抽象概念时,名字很重要啊!
后来搜了下,原来Future在java中也有这个概念,可以参考这篇中文的文章(把callback和actor鄙视了一通),大体上讲就是把一个异步的程序转为顺序的写法:
ExecutorService executor = ...//copy from jdk doc ArchiveSearcher searcher = ... void showSearch(final String target) throws InterruptedException { Future<String> future = executor.submit(new Callable<String>() { public String call() { return searcher.search(target); }}); displayOtherThings(); // do other things while searching try { displayText(future.get()); // use future 这个地方会被block } catch (ExecutionException ex) { cleanup(); return; }
如果会被block的话,还有啥意义呢?不过代码的逻辑清楚很多。
正式的解释在wikipeida上面有:http://en.wikipedia.opreiki/Futures_and_promises Futures and promises.
看这篇dojo tutorial,你发现原来dojo.then其实对应上面的future,也就是一个包含返回数据的对象(js不需要用get方法),dojo.when的用处就是使普通的数据和“将来”的数据统一使用。Wikipedia对java需要get的方式为显式的future,而dojo的为隐式的。
在Actor模式中也会用到future,具体参考Akka的这篇文档。(Akka的文档比Scala完善很多,而且有java的版本,上手很容易。上面说Future is Monad,晕啊)
Future[Object] future = actorRef.sendRequestReplyFuture[Object](msg); Object result = future.get(); //Block until result is available, usually bad practice
actor之间可以用message来访问,上面的方式方便了非actor访问actor。如果系统明确的划分成几个Actor,则future使用的地方很少。