使用callback是能有效的达成异步不错,但是当业务变得庞大时,很多地方我们都要使用到异步调用。但如果异步调用嵌套多次,或者调用之间的依赖关系复杂的话,难免代码会变得混乱不堪。举个例子,假设我们需要依次调用服务A、B、C、D,我们就不得不把调用下一个接口的代码写在上一个接口的回调函数中。
这时,future/promise的异步调用方式就应运而生了,采用这种方式我们定义回调函数中完成当前回调逻辑后,返回一个future对象即可。future对象表示着这个回调逻辑已经完成,但是具体后续还要进行什么操作,我们都不关心。之后的调用都交给then(bind(&handlernext))来解决。所以他的代码看上去就要清晰明了的多了。下面是两种模式代码之间的对比:
采用callback模式下的异步多层调用:
//以下为伪代码,仅为了方便理解future/promise的概念
callbackA(...)
{
... //完成回调的业务逻辑
Proxy->async_doSomething(callbackB, param1, param2...); //异步调用B服务
}
callbackB(...)
{
... //完成回调的业务逻辑
Proxy->async_doSomething(callbackB, param1, param2...); //异步调用C服务
}
callbackC(...)
{
... //完成回调的业务逻辑
Proxy->async_doSomething(callbackB, param1, param2...); //异步调用D服务
}
callbackD(...)
{
... //完成回调的业务逻辑
}
main()
{
...
Proxy->async_doSomething(callbackA, param1, param2...); //异步调用A服务
...
}
采用future/promise的异步多层调用:
callbackA(...)
{
... //完成回调的业务逻辑
return Proxy->promise_async_doSomething(param1, param2...) //调用下一步的服务并将其传出
}
callbackB(...)
{
... //完成回调的业务逻辑
return Proxy->promise_async_doSomething(param1, param2...) //调用下一步的服务并将其传出
}
callbackC(...)
{
... //完成回调的业务逻辑
return Proxy->promise_async_doSomething(param1, param2...) //调用下一步的服务并将其传出
}
callbackD(...)
{
... //完成回调的业务逻辑
}
main()
{
...
Proxy->promise_async_doSomething(param1, param2...).then(bind(&callbackA)).then(bind(&callbackB)).then(bind(&callbackC)).then(bind(&callbackD));
...
}
看到上面的示例,我们发现,future/promise的代码更加的简洁,使得可读性更高。
这得益于promise_async_dosomething 和 then 的返回值都是future。所有回调函数都只需要调用接口并返回“已经调用接口”这一“事实”,而不关心下一步的回调函数在哪里,回调函数之间的调用关系都只通过Future.then()来连接。这样便可以很清楚地看出服务之间的调用关系是线性的。
串行异步
下面用一个简单例子来进一步学习future/promise的用法:有一个服务getBigger(int a,int b),能获取到2个int中的较大值。现在使用异步调用来获取到三个int中的最大值。
//#include<GetBiggerServer.h>
#include"servant/Communicator.h"
#include"servant/ServantProxy.h"
#include"servant/Application.h"
#include"GetBiggerServer.h"
using namespace std;
using namespace taf;
using namespace MTT;
bool flag = false;
//TODO:第一个异步调用,需要传入prx,原因是return的future去调下一个异步调用,需要proxy代理指针
promise::Future< GetBiggerServerPrxCallbackPromise::PromisegetBiggerPtr > handler1(GetBiggerServerPrx prx,
const promise::Future< GetBiggerServerPrxCallbackPromise::PromisegetBiggerPtr>& f)
{
try
{
GetBiggerServerPrxCallbackPromise::PromisegetBiggerPtr pResult = f.get();
cout<<"the return value in first calling is "<< pResult-