AngularJS 1.6.1中$q Promise完成是否依赖返回?then未显式return是否引发竞态?
AngularJS 1.6.1 + $q:then无return时的竞态条件疑问解答
嘿,这个问题抓得很准,刚好戳中了$q promise链的核心行为逻辑,我来给你掰扯清楚~
首先明确结论:在你的场景下(then回调里只是同步把数据赋值到$scope),即使不写return,也不会出现竞态条件。原因得从$q的then方法和$q.all的工作机制说起:
1. $q.then的核心行为
不管你在then的回调函数里return什么(哪怕啥都不写,相当于return undefined),then都会返回一个全新的promise对象。这个新promise的resolve时机是:
- 当你的
then回调函数完全执行完毕之后,它会自动resolve为你return的值(或者undefined)。
也就是说,只要then里的同步代码没执行完,这个新promise就不会被resolve。
2. 你的场景里$q.all的等待逻辑
你代码里传给$q.all(promises)的数组,其实是每个服务调用后then返回的新promise,而不是服务本身返回的原始请求promise。举个直观的代码例子:
var promises = [ dataOneService.getData().then(function(data) { $scope.dataOne = data; // 同步赋值操作 // 没有return语句 }), dataTwoService.getData().then(function(data) { $scope.dataTwo = data; // 同步赋值操作 // 没有return语句 }) ]; $q.all(promises).then(function() { // 这里的代码一定会在两个$scope赋值完成后才执行 });
在这个流程里:
dataOneService.getData()的请求完成,原始promise resolve;- 执行对应的
then回调,把data赋值给$scope.dataOne(同步操作,瞬间完成); - 这个
then返回的新promise被resolve; - 同理完成
dataTwoService的整个流程; - 只有当两个
then返回的promise都resolve了,$q.all才会进入自己的then回调。
所以你完全不用担心$q.all提前兑现,而赋值操作还没做完的情况——同步赋值的逻辑肯定会在$q.allresolve之前执行完毕。
3. 什么时候才会出问题?
如果你的then回调里包含异步操作,而且没有return这个异步操作的promise,这时候才会出现竞态条件。比如:
var riskyPromise = dataOneService.getData().then(function(data) { // 这里有个异步操作,但没返回它的promise setTimeout(function() { $scope.dataOne = data; $scope.$apply(); }, 1000); }); $q.all([riskyPromise]).then(function() { // 这里执行时,setTimeout的回调还没触发,$scope.dataOne还是undefined });
这种情况下,then返回的promise会在同步代码执行完(也就是setTimeout调用完,但回调还没执行)就立刻resolve,导致$q.all提前兑现,而异步赋值还没完成。这时候你就需要return异步操作的promise,让$q.all等待它完成。
内容的提问来源于stack exchange,提问作者monstercode
相关产品推荐
相关产品推荐

