通过回调其他控制器来共享promise中的数据

Shl*_*omo 2 promise angularjs angular-promise

控制器A通过承诺发送请求.在另一个控制器B中同时运行回调函数的最佳方法是什么?通过原始回调中的服务进行广播,并在另一个控制器中进行侦听.是否有可能将承诺传递给控制器​​B?

选项1:

// controller A
service.doAjax().then( function( data ) { 
// controller A callback 
// should I broadcast "data" and listen for the event in controller B ?
} );

// controller B
$rootScope.$on();
// ... listen for the event sent from controller A to get "data
Run Code Online (Sandbox Code Playgroud)

选项2:

// controller A
var promise = service.doAjax(); 
shareService.sharePromise( promise ); // Sharing the promise with broadcast

// controller B
// get promise from shareService via $on()
promise.then( function( data) {} );
Run Code Online (Sandbox Code Playgroud)

选项2的问题是回调函数将被执行多次.我不想共享数据,但执行回调.

Ben*_*aum 5

您可以分享承诺而不是共享数据.在您的服务中:

var cached = null; // assumes the ajax doesn't return a falsey value
function doAjax(){
    if(!cached) cached = $http.get(...); // actual request
    return cached;
}
Run Code Online (Sandbox Code Playgroud)

这样,当两个控制器调用它时,它们将获得相同的请求 - 并且它实际上将由任何先调用它的人触发.通过缓存承诺(而不是数据),您也可以阻止一类有趣的竞争条件.

如果您不想总是缓存结果,那么您可以使用一种特殊的方法来"实现某种屏障或集合模式""您想要等待的人":

var awaiters = {};
function randevouz(who){
    return new $q(function(resolve, reject){
         awaiters[who] = (awaiters[who] || []).concat(resolve); // add new
    });
}
function arrived(who){
    (awaiters[who] || []).forEach(function(x){ x(); });
}
Run Code Online (Sandbox Code Playgroud)

哪个让你在控制器B中调用:

randevouz("B").then(function(){
    // a let me know they're ready   
});
Run Code Online (Sandbox Code Playgroud)

在A:

doAjax().then(function(){
    arrived("A");
});
Run Code Online (Sandbox Code Playgroud)