我所使用的异步编程

JavaScript在异步处理上十分方便,最一开始用到异步是JavaScript封装框架jQuery来请求后台的代码
$.post(url,param,callback)
而这种方式需要提供回调函数
但是回调函数可能会出现这样的窘境:
一个回调的经典场景:nodejs中mongoDB的查询使用
var p_client = new Db('integration_tests_20', new Server("127.0.0.1", 27017, {}), {'pk':CustomPKFactory});
p_client.open(function(err, p_client) {
    p_client.dropDatabase(function(err, done) {
        p_client.createCollection('test_custom_key', function(err, collection) {
            collection.insert({'a':1}, function(err, docs) {
                collection.find({'_id':new ObjectID("aaaaaaaaaaaa")}, function(err, cursor) {
                    cursor.toArray(function(err, items) {
                        test.assertEquals(1, items.length);

                        // Let's close the db
                        p_client.close();
                    });
                });
            });
        });
    });
});

为了解决多层异步不利于理解和调错的问题,ES6引入了新的对象,Promise
mozilla官方对它的定义是:
Promise 对象用于异步(asynchronous)计算.。一个Promise对象代表着一个还未完成,但预期将来会完成的操作
在我看来Promise是一个包含自执行器的状态机
我们模拟一下Promise的实现
//全局宏定义
var PENDING = 0;
var FULFILLED = 1;
var REJECTED = 2;
//Promise构造函数
function Promise(fn){
    var self = this;
    self.state = PENDING;//初始化状态
    self.value = null;//存储异步结果的对象变量
    self.handlers = [];//存储回调函数,这里没保存失败回调函数,因为这是一个dome
    //异步任务成功后处理,这不是回调函数
    function fulfill(result){
        if(self.state === PENDING){
            self.state = FULFILLED;
            self.value = result;
            for(var i=0;i<self.handlers.length;i++){
                self.handlers[i](result);
            }
 
        }
    }
 
    //异步任务失败后的处理,
    function reject(err){
        if(self.state === PENDING){
            self.state = REJECTED;
            self.value = err;
        }
    }   
    fn&&fn(fulfill,reject);
 
};
 
//使用then方法添加回调函数,把这次回调函数return的结果当做return的promise的resolve的参数
Promise.prototype.then = function(onResolved, onRejected){
    var self = this;
    return new Promise(function(resolve, reject){
        var onResolvedFade = function(val){
            var ret = onResolved?onResolved(val):val;//这一步主要是then方法中传入的成功回调函数通过return来进行链式传递结果参数
            if(Promise.isPromise(ret)){//回调函数返回值也是promise的时候
                ret.then(function(val){
                    resolve(val);
                });
            }
            else{
                resolve(ret);
            }
        };
        var onRejectedFade = function(val){
            var ret = onRejected?onRejected(val):val;
            reject(ret);
        };
        self.handlers.push(onResolvedFade);
        if(self._status === FULFILLED){
            onResolvedFade(self._value);
        }
 
        if(self._status === REJECTED){
            onRejectedFade(self._value);
        }
    });
}
使用如下:
function p(value){
    var pms = new Promise(function(resolve, reject){
        setTimeout(function(){
            resolve(value);;
        }, 1000);
    });
    return pms;
}
p(1).then(function(result){
    console.log('the result is ',result);//the result is 2 
    return result;
}).then(function(result){
    console.log(++result);//2
});
成功进入resolve参数,失败则进入reject函数
ES6中提供的Promise还有捕获异常的catch组件
更进一步,ES6中实现了C#中存在的async   await 关键字,如下:
其中async对修饰函数做了一个Promise封装
 
function timeout(ms){
    return new Promise((resolve)=>{
        setTimeout(resolve,ms);
    })
}
 
async function asyncPrint(value,ms){
    await timeout(ms);
    console.log(value);
}
 
asyncPrint('hello world',1000);
 
console.log('end');
APM
C#中对应的叫做APM( Asynchronous Programming Model)
基于回调的异步实现,类似的实现BeginInvoke异步方法的类
 
java中的异步回调稍微麻烦一些,可以自己实现
public class CallBackTest extends AbstractCallBack {
      public CallBackTest(CallHandler handler) {
            super(handler);
      }
      public static void main(String[] args) {
            CallBackTest callTest = new CallBackTest(new CallHandler() {
                  @Override
                  public void handler(String param) {
                        System.out.println("处理参数:" + param);
                  }
            });
            callTest.start("参数1");
      }
      @Override
      void after() {
            System.out.println("回调处理");
      }
}
//异步处理
abstract class AbstractCallBack {
      private CallHandler callHandler;
      public final void start(final String param) {
            new Thread(new Runnable() {
                  @Override
                  public void run() {
                        callHandler.handler(param);
                        after();
                  }
            }).start();       
      }
      public AbstractCallBack(CallHandler handler) {
            this.callHandler = handler;
      }
      abstract void after();
}
//回调函数接口
interface CallHandler {
      public void handler(String param);
}
 
TAP 基于任务的异步模式,Task-based Asynchronous Pattern
Java并发包中已经有相应的实现了,我们可以用 FutureTask达到相应的效果:
public class futureTaskTest {
      public static void main(String[] args) {
            ExecutorService executor = Executors.newCachedThreadPool();
            for (int i = 0; i < 5; i++) {
                  Callable<String> c = new Task();
                  MyFuture ft = new MyFuture(c);
                  executor.submit(ft);
            }
            executor.shutdown();
      }
}
class MyFuture extends FutureTask<String> {
      public MyFuture(Callable<String> callable) {
            super(callable);
      }
      public void done() {
            System.out.println(" 线程执行完毕!~");
      }
}
class Task implements Callable<String> {
      @Override
      public String call() throws Exception {
            // TODO Auto-generated method stub
            Thread.sleep(1000);
            System.out.println(" 执行中");
            return Thread.currentThread().getName();
      }
}
Event-based Asynchronous Pattern基于事件的异步
参考我先前的一篇文章,基于观察者模式实现java的事件:http://www.cnblogs.com/wanglao/p/5305076.html
将其异步化,改变事件监听者(事件处理),然后在事件源的触发器中增加线程控制:
abstract class Handler implements EventListener, Runnable {
      EventState state;
      public Handler(EventState state) {
            this.state = state;
      }
      public void doHandler() {
            System.out.println("handler1 执行了,现在状态是:" + state);
      }
      public void run() {
            doHandler();
      }
}
//事件执行
             protected void notifies(EventState sate){
                   if ( eventListeners.size()>0) {
                         for (Handler handler : eventListeners) {
                              new Thread(handler).start();
                        }
                  }
            }
另外,一些设计模式也是天生适合异步多线程环境,比如生产者-消费模式。
 
 参考:http://www.cnblogs.com/zhaopei/p/async_one.html
 
原文地址:https://www.cnblogs.com/wanglao/p/6564799.html