I want to watch changes in my services like in my system logs when there's someone who login the getlogs function must trigger how to achieve this ???
dashboard.controller
function getLogs() {
return dataservice.getLogs().then(function (data) {
vm.logs = data;
return vm.logs;
});
}
dataservice.js
function getLogs() {
return $http.get('/api/timeLogs')
.then(success)
.catch(fail);
function success(response) {
return response.data;
}
function fail(e) {
return exception.catcher('XHR Failed for getPeople')(e);
}
}
I've tried this but its not working
$scope.$watch('dataservice.getLogs()', function () {
getLogs();
}, true);
This is a case for observable pattern where you subscribe for changes on your service
app.service('dataservice', function($http) {
var subscribers = [];
var addSubscriber = function(func){
subscribers.push(func);
}
var notifySubscribers = function(){
for(var i = 0; i< subscribers.length; i++){
subscribers[i](); //invoke the subscriber
}
};
var addLog = function(){
//let's say that the logs are added here
//then notify the subscribers that a new log has been added
notifySubscribers();
};
var getLogs = function() {
return $http.get('/api/timeLogs')
.then(success)
.catch(fail);
function success(response) {
return response.data;
}
function fail(e) {
return exception.catcher('XHR Failed for getPeople')(e);
}
};
return {
addSubscriber: addSubscriber,
addLog: addLog,
getLogs: getLogs
}
});
Then in your controller add a subscriber function to the service
dataservice.addSubscriber(function(){
console.log('new log added');
dataservice.getLogs();
});
NOTE: this can also be done with the RxJs library
if you want to check and get data's change from server, watching a service is not for that, use a polling service.
you check for every 1sec (for example) from a server:
example:
$interval(function() {
dataservice.getLogs().then(function(data) {
vm.logs = data;
});
}, 1000);
or much better:
getLogs = function () {
dataservice.getLogs().then(function(data){
vm.logs = data;
$timeout(getLogs, 1000)
});
}
Related
Using JavaScript and AngularJS, I have a controller function looking to set a bool based on the return of a service call, which awaits the return of an API call. How do I write the controller function to wait for the API response?
Controller...
var someBoolValue = false;
function firstCheck() {
// function checks other things
if (someCheck) {
// how do I set someBoolValue to await the response, this code did NOT work
SomeService.CheckforSomething(data, moreData).then(function (response) {
someBoolValue = response;
});
}
Service...
function CheckforSomething(data, moreData) {
var anImportantNumber = null;
var anotherNumber = 456;
// function does other things
anImportantNumber = 123;
if (someCondition) {
ApiService.GetMyData()
.then(function (data) {
anImportantNumber = data.ThisValue.WRT;
}
}
return (anImportantNumber != anotherNumber);
}
API Service...
function GetMyData() {
uri = 12345;
$http.get(uri)
.then(function (response) {
dererred.resolve(response.data)
}
return deferred.promise;
}
wifiservice.js:
angular.module('app.WifiServices', [])
.factory('WifiService', function(){
var unique_array = angular.fromJson('[]');
function win_wifi(e){
alert("Success");
}
function fail_wifi(e){
alert("Error");
}
function connectWifi(wifi_ssid){
WifiWizard.connectNetwork(wifi_ssid, win_wifi, fail_wifi);
}
function listHandler(a){
var network_array = [];
for(var i=0; i<a.length; i++){
network_array.push("SSID: " + a[i].SSID + " Signal: " + a[i].level);
}
unique_array = network_array.filter(function(elem, pos) {
return network_array.indexOf(elem) == pos;
});
// alert("Wifi List Ready!");
}
function getScanResult(){
WifiWizard.getScanResults(listHandler, failNetwork);
}
function successNetwork(e){
window.setTimeout(function(){
getScanResult();
}, 3000);
}
function failNetwork(e){
alert("Network Failure: " + e);
}
window.setTimeout(function(){
WifiWizard.startScan(successNetwork, failNetwork);
}, 1000);
return {
list: function(){
return unique_array;
},
connectionToWifi: function(name){
connectWifi(name);
}
};
});
My whole controller:
app.controller('WifiController', ['$scope', 'WifiService', function($scope, WifiService) {
$scope.wifiList = [];
window.setTimeout(function() {
$scope.wifiList = WifiService.list();
// alert($scope.wifiList);
$scope.$apply();
}, 5000);
$scope.getList = function() {
$scope.wifiList = WifiService.list();
return $scope.wifiList;
}
$scope.connectWifi = function(name) {
WifiService.connectionToWifi(name);
}
$scope.checkin = function() {
$scope.getList()
.then(function(result) {
console.log(result);
});
}
}]);
What I am trying to do is, to call the $scope.getList(), which returns a list of the surrounding wifi SSIDs, then within $scope.checkin() I would like to process those data.
Since scanning needs some time I have to wait the getList function to finish, thats Why I am trying to use .then, but it gives me the error says on the title. Any ideas?
How to create a AngularJS promise from a callback-based API
To create an AngularJS promise from a callback-based API such as WifiWizard.connectNetwork, use $q.defer:
function connectWifi(wifi_ssid) {
var future = $q.defer();
var win_wifi = future.resolve;
var fail_wifi = future.reject;
WifiWizard.connectNetwork(wifi_ssid, win_wifi, fail_wifi);
return future.promise;
};
The above example returns a $q Service promise that either resolves or rejects using the callbacks from the API.
Well, I came up with something different:
var unique_array = [];
$scope.wifiList = [];
$ionicLoading.show({
template: "Scanning surrounding AP's..."
});
window.setTimeout(function() {
$scope.wifiList = WifiService.list();
// alert($scope.wifiList);
while ($scope.wifiList == []) {
console.log('Scanning...');
}
$scope.$apply();
$ionicLoading.hide();
}, 5000);
What I realize is that the scanning starts once I load the view. So, I added an IonicLoader to force the user to wait, and not be able to press any buttons till the scan is finished. So no function shall wait one another. Not quite code-wise correct, but it does what I need.
I am fetching the details from an API using Angular Service and I want to return only the matching items. Meaning, after I type some text, I will click a button, which will call a function in a Controller which will call the Service to get the details.
Now my problem, is that it returns the entire list not the filtered list, I have stored filter result into an array I want to return that array(foundItems).
This is my code
(function() {
angular.module('NarrowItDownApp',[])
.constant('url',"https://davids-restaurant.herokuapp.com/menu_items.json")
.controller('NarrowItDownController',['$scope','MenuSearchService',function($scope,MenuSearchService) {
var items=this;
items.searchitem="";
items.getitems=function() {
MenuSearchService.getMatchedMenuItems(items.searchitem).then(function(response) {
this.found=response.data;
console.log(this.found);
})
.catch(function(response) {
this.found=response.data;
console.log(this.found);
});
};
}])
.service('MenuSearchService',['$http','url',function($http,url) {
var service=this;
service.getMatchedMenuItems=function(searchitem)
{
var foundItems=[];
var key;
return $http.get(url).success(function(data) {
for(var i=0;i<data.menu_items.length;i++)
{
var temp=data.menu_items[i];
//Old method
/*for(key in temp)
{
if(temp.hasOwnProperty(key))
{
console.log(temp[key])
}
}*/
Object.keys(temp).forEach(function(items)
{
if(searchitem==temp[items])
{
foundItems.push(temp);
}
});
};
console.log(foundItems);
return foundItems;
})
.error(function(data) {
console.log('error');
return data;
});
return foundItems;
};
}]);
})();
Now my problem, is that it returns the entire list not the filtered list, I have stored filter result into an array I want to return that array(foundItems).
The reason that the service returns the entire list is that the .success and .error methods ignore return values. Use .then and .catch instead.
service.getMatchedMenuItems=function(searchitem)
{
var foundItems=[];
var key;
//return $http.get(url).success(function(data) {
//USE .then method
return $http.get(url).then(function(response) {
var data = response.data;
for(var i=0;i<data.menu_items.length;i++)
{
var temp=data.menu_items[i];
Object.keys(temp).forEach(function(items)
{
if(searchitem==temp[items])
{
foundItems.push(temp);
}
});
};
console.log(foundItems);
return foundItems;
})
//.error(function(data) {
//USE .catch method
.catch(function(errorResponse) {
console.log(errorResponse.status);
//return data;
//THROW to chain rejection
throw errorResponse;
});
//return foundItems;
};
Also it is important to use a throw statement in the rejection handler. Otherwise the rejected promise will be converted to a successful promise.
For more information, see Angular execution order with $q.
You can use promise for that Promise
(function() {
angular.module('NarrowItDownApp', [])
.constant('url', "https://davids-restaurant.herokuapp.com/menu_items.json")
.controller('NarrowItDownController', ['$scope', 'MenuSearchService', function($scope, MenuSearchService) {
var items = this;
items.searchitem = "";
items.getitems = function() {
MenuSearchService.getMatchedMenuItems(items.searchitem).then(function(data) {
for (var i = 0; i < data.menu_items.length; i++) {
var temp = data.menu_items[i];
//Old method
/*for(key in temp)
{
if(temp.hasOwnProperty(key))
{
console.log(temp[key])
}
}*/
Object.keys(temp).forEach(function(items) {
if (searchitem == temp[items]) {
foundItems.push(temp);
}
});
};
this.found = foundItems);
console.log(this.found);
})
.catch(function(response) {
this.found = response.data;
console.log(this.found);
});
};
}])
.service('MenuSearchService', ['$http', 'url', function($http, url) {
var service = this;
service.getMatchedMenuItems = function(searchitem) {
var foundItems = [];
var key;
return $http.get(url);
};
}]);
})();
I am implementing long polling to know the state of some long running event on the server side. I create my own factory that will notify me when a server event triggers. Here is the factory.
.factory("$httpPolling", function ($http) {
function $httpPolling($httpService) {
var _responseListener, _finishListener;
var cancelCall = false;
var _pollId;
function waitForServerCall(id) {
console.log("executing waitForServerCall");
$httpService.get(href("~/polling/" + id))
.success(function (response) {
var cancelPolling = _responseListener(response);
if (cancelPolling || cancelCall) {
return;
}
else {
waitForServerCall(id);
}
});
};
function _sendData(httpMethod, url) {
var pollingId = guid();
_pollId = pollingId;
if (url.split("?").length == 2) {
url += "&pollid=" + pollingId;
}
else {
url += "?pollid=" + pollingId;
}
if (httpMethod == 0) {
$httpService.get(url).success(function (response) {
if (_finishListener) {
_finishListener(response);
}
cancelCall = true;
});
}
else {
$httpService.post(url).success(function (response) {
if (_finishListener) {
_finishListener(response);
}
cancelCall = true;
});
}
}
var $self = this;
this.get = function (url) {
_sendData(0,url);
return $self;
};
this.post = function (url) {
_sendData(1, url);
return $self;
};
this.listen = function (_listener) {
_responseListener = _listener;
waitForServerCall(_pollId);
return $self;
}
this.finish = function (_finish) {
_finishListener = _finish;
return $self;
}
}
return new $httpPolling($http);
});
Where the sintax of usage should be:
$httpPolling.get("url")
.listen(function(event){
// fires when server event happend
})
.finish(function(response){
// fires when the long running process finish
});
The problem is that _sendData method does not execute asynchronously because the waitForServerCall only executes the ajax call when the _sendData(long running process) method get the response from the server.
Why? Is this an angular behavior?
Angular $httpProvider has an option provided for async http calls, which is set to false as default value.
Try
app.config(function ($httpProvider) {
$httpProvider.useApplyAsync(true);
});
I'm brand new to angular, so I'm probably doing things all wrong. My query is returning an array of objects like it should be. I then do a click event to test the post..it hits my web api just fine...but then it returns that same array from my get. I'm guessing this is cached? Why would my post show the results of my earlier get?
Edit - Sorry, I could have been more clear. When I run my saveTest method, a post fires and my array saves, however the 'result' variable of that save..is the array from my original get.
app.directive('referenceSection', function () {
return {
restrict: 'E',
templateUrl: '/app/loanapplication/views/reference-section.html',
controller: function ($scope, referenceService) {
$scope.json = angular.toJson($scope.referenceArray);
$scope.referenceArray = [];
referenceService.query().$promise.then(function (result) {
$scope.referenceArray = result;
}, function () {
alert("fail");
});
$scope.saveTest = function () {
referenceService.save(angular.toJson($scope.referenceArray)).$promise.then(function (result) {
var x = result;
}, function () {
alert("save fail");
});
}
}
};
});
Service
app.factory('referenceService', function ($resource) {
var requestUri = '/api/reference';
return $resource(requestUri)
});
Web api
public class ReferenceController : BaseController
{
public HttpResponseMessage Get()
{
List<WebReference> references = new List<WebReference>();
WebReference reference = new WebReference();
WebReference reference2 = new WebReference();
reference.Name = "Andrew";
reference.Relationship = "QuickSupport";
reference.Id = 1;
reference2.Name = "Josh";
reference2.Relationship = "Hansen";
reference2.Id = 2;
references.Add(reference);
references.Add(reference2);
if (references == null) throw new HttpResponseException(HttpStatusCode.NotFound);
return Request.CreateResponse<IEnumerable<WebReference>>(HttpStatusCode.OK, references);
}
public HttpResponseMessage Post([FromBody]WebReference[] references)
{
try
{
var msg = new HttpResponseMessage(HttpStatusCode.Created);
return msg;
}
catch (Exception e)
{
throw new HttpResponseException(HttpStatusCode.Conflict);
}
}
}
}
referenceService.query().$promise.then(function (result) {
$scope.referenceArray = result;
After this, you need to call $scope.$apply() to inform angular of your changes made to be bound. If I guessed your question correctly .
:-)
From where you are reading response? From x that is not available outside then function or it is mistake to not attach it to referenceArray
referenceService.save(angular.toJson($scope.referenceArray)).$promise
.then(function (result) {
var x = result;
}, function () {
alert("save fail");
});