javascript - 关于 Promise 异步操作的疑惑,以及如果更优雅的编写
问题描述
这几天看了翻了很多关于 「promise」相关技术贴,看的是眼花缭,一知半解大概了解其作用。
先说说问题吧,项目中用到最多少就是Ajax,有个很不爽的问题「多条ajax依赖请求」假设: R1 > R2( r1_result ) > R3( r2_result ),最省事的做法全部都同步了吧,结果就是体验很糟糕,页面一度假死,loading 也不转了,使用异步操令人恶心的就是一层套一层的回调,以及后续更多的依赖操作。
生命在于折腾,于是就回到了第一段中各种翻阅,看到某位兄台对 promise 原理刨析,下面引用这位兄台中的code,http://malcolmyu.github.io/ma...
function Promise(fn) { var state = ’pending’; var value; var deferred = null; function resolve(newValue) { if(newValue && typeof newValue.then === ’function’) { newValue.then(resolve, reject); return; } state = ’resolved’; value = newValue; if(deferred) { handle(deferred); } } function reject(reason) { state = ’rejected’; value = reason; if(deferred) { handle(deferred); } } function handle(handler) { if(state === ’pending’) { deferred = handler; return; } var handlerCallback; if(state === ’resolved’) { handlerCallback = handler.onResolved; } else { handlerCallback = handler.onRejected; } if(!handlerCallback) { if(state === ’resolved’) {handler.resolve(value); } else {handler.reject(value); } return; } var ret = handlerCallback(value); handler.resolve(ret); } this.then = function(onResolved, onRejected) { return new Promise(function(resolve, reject) { handle({onResolved: onResolved,onRejected: onRejected,resolve: resolve,reject: reject }); }); }; fn(resolve, reject);}
看完我不禁又疑惑了, then( function(){ do... } ),这丫还不是个回调嘛,难道是折腾的意义就是套个语法糖(我不信)。
存在即合理,所以最后怎样合理使用 promise, 如何更优雅操作ajax流程?顺便提下有使用 ( axios fetch.js )感觉如何?
问题解答
回答1:Promise 就是为了解决异步流程控的而生的,其使用核心就是then方法; then初看起来是很像回调,但then的特质是可以处理异常及链式写法. 打个比方,几个ajax请求依赖如下:
A1 -> A2; Aa -> Ab;Ab + Ac -> Ad;A2 + Ad -> Ax;
如果用Promise,代码会很清晰 首先准备好 A1,A2,Aa,Ab,Ac,Ad,Ax 都是根据依赖反回promise对像的函数,我就不写了 然后可以看Promise表演了:
Promise.all([ A1().then(A2), //A1 -> A2 Promise.all([Aa().then(Ab), //Aa -> AbAc() //Ac ]).then(Ad) //Ab + Ac -> Ad;]).then(Ax,Err) //A2 + Ad -> Ax.then(function(v){//完成})
A1,Aa和Ac没有依赖,会并发执行,之后会根据依赖完成的情况来继续, 不论哪一个Ajax出问题,都会触发最后的Err事来统一处理错误; 如果你用回调来写一下试试,要么效率不好,要么回调方法里加一堆代码来判断依赖的情况.
参考代码:
//首先准备好 A1,A2,Aa,Ab,Ac,Ad,Ax 都是基于回调的异步函数var a2,ab,ac,ad; //用来保存完成情况的变量function runAx(){ if(a2 == undefined || ad == undefined) return; //判断依赖 Ax(a2,ad,function(e,v){//完成 })}function runAd(){ if(ab == undefined || ac == undefined) return; //判断依赖 Ad(ab,ac,function(e,v){ad = v;runAx(); })}A1(function(e,v){ A2(v,function(e,v){a2 = v;runAx(); })})Aa(function(e,v){ Ab(v,function(e,v){ab = v;runAd(); })})Ac(function(e,v){ ac = v; runAd();})
上面的代码没有去处理error,就这么长了,如果依赖再复杂一点,可以想象代码量,而且容易写错;
回答2:你的理解基本上对,实际上Promise没简化多少,只是减少了嵌套的层级。
所以,终极解决方案就是Async/Await,题主可以去查查看资料。
回答3:优雅就是一个then接一个then,把回调圣诞树造型撸直,这就是Promises的贡献。
我写程序要七八个回调嵌套,Promises爽的一比。
你觉得then写法都嫌麻烦,那就不要用咯,用Async/Await
