我希望两个不同的控制器在服务中解决一些promise之后运行不同的函数(我不希望每次控制器需要数据时这个服务都发出一个http请求,我只想要一个http请求。)
我有一个提出请求并获得承诺的服务。我希望controller1看到这个分辨率,然后运行一些代码。然后我想让controller2也看到这个promise解析并运行一些代码(基本上是多个then()方法,它们运行在同一个promise但是来自不同的文件)。我怎么能这样做呢?
我看到的所有示例都有一个控制器在某个承诺解析后运行代码,但没有多个控制器监听同一个承诺解析。
这里是我从这篇文章借用的一些代码(生病添加一个'母亲控制器'来说明我的例子,我不希望儿子服务能够两次进行他的http调用):http://andyshora.com/promises-angularjs-explained-as-cartoon.html
儿子服务
app.factory('SonService', function ($http, $q) {
return {
getWeather: function() {
// the $http API is based on the deferred/promise APIs exposed by the $q service
// so it returns a promise for us by default
return $http.get('http://fishing-weather-api.com/sunday/afternoon')
.then(function(response) {
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
return $q.reject(response.data);
}
}, function(response) {
// something went wrong
return $q.reject(response.data);
});
}
};
});
父亲控制员:
// function somewhere in father-controller.js
var makePromiseWithSon = function() {
// This service's function returns a promise, but we'll deal with that shortly
SonService.getWeather()
// then() called when son gets back
.then(function(data) {
// promise fulfilled
if (data.forecast==='good') {
prepareFishingTrip();
} else {
prepareSundayRoastDinner();
}
}, function(error) {
// promise rejected, could log the error with: console.log('error', error);
prepareSundayRoastDinner();
});
};
母亲控制员:
var makePromiseWithSon = function() {
SonService.getWeather()
// then() called when son gets back
.then(function(data) {
// promise fulfilled
if (data.forecast==='good') {
workInTheGarden();
} else {
sweepTheHouse();
}
}, function(error) {
// promise rejected, could log the error with: console.log('error', error);
sweepTheHouse();
});
};
答案 0 :(得分:1)
要让您的工厂服务仅获取网址,请将httpPromise存储在工厂服务中。
app.factory('SonService', function ($http) {
var weatherPromise;
function getWeather() {
return $http.get('http://fishing-weather-api.com/sunday/afternoon')
.then(function(response) {
if (typeof response.data === 'object') {
return response.data;
} else {
// invalid response
throw response;
}
}, function(response) {
// something went wrong
throw response;
});
}
function sonService() {
if (!weatherPromise) {
//save the httpPromise
weatherPromise = getWeather();
}
return weatherPromise;
}
return sonService;
});
答案 1 :(得分:1)
简单的答案,在非角度特定的(但很容易应用于Angular)方式,是创建一个缓存ON-OUTBOUND-REQUEST的服务(而不是像大多数系统那样缓存返回值)。
function SearchService (fetch) {
var cache = { };
return {
getSpecificThing: function (uri) {
var cachedSearch = cache[uri];
if (!cachedSearch) {
cachedSearch = fetch(uri).then(prepareData);
cache[uri] = cachedSearch;
}
return cachedSearch;
}
};
}
function A (searchService) {
var a = this;
Object.assign(a, {
load: function ( ) {
searchService.getSpecificThing("/abc").then(a.init.bind(a));
},
init: function (data) { /* ... */ }
});
}
function B (searchService) {
var b = this;
Object.assign(b, {
load: function ( ) {
searchService.getSpecificThing("/abc").then(b.init.bind(b));
},
init: function (data) { /* ... */ }
});
}
var searchService = SearchService(fetch);
var a = new A(searchService);
var b = new B(searchService);
a.load().then(/* is initialized */);
b.load().then(/* is initialized */);
他们共享相同的承诺,因为他们正在谈论的服务缓存并返回相同的承诺。
如果您想要安全,可以缓存一个承诺,然后返回根据缓存的承诺解决(或拒绝)的新承诺实例。
// instead of
return cachedSearch;
// replace it with
return Promise.resolve(cachedSearch);
每次发出请求时,每个用户都会获得一个新实例,但每个实例也会根据原始缓存调用传递或失败。
当然,你可以更进一步,并在缓存上设置一个时间限制,或者使缓存无效,或者等等......
将其转换为Angular也是一个快照
SearchService
是一项服务A
和B
是控制器$http
代替fetch
(虽然fetch非常漂亮)fetch( ).then(prepareData)
中您成功转换JSON数据; $http
,您将返回response.data
,因为您的用户不想这样做
无论哪种方式,您每次出站呼叫都只执行一次该操作,因此也将其缓存$q
(和q
方法)代替原生Promise
angular.extend
,而不是Object.assign