Making Sync calls using promises Angular JS factories - javascript

I am trying to make sync calls using a factory pattern.
$scope.doLogin = function (username, password, rememberme) {
appKeyService.makeCall().then(function (data) {
// data = JSON.stringify(data);
debugAlert("login controller app key service"+data);
var appkeyvalue = data.d.appkey;
sessionConfigurationService.setBasicToken(appkeyvalue);
loginService.makeCall(username, password, rememberme).then(function (accessTokenData) {
if (accessTokenData.access_token !== "")
{
sessionConfigurationService.setAccessTokenData(accessTokenData.access_token);
userPreferencesService.makeCall().then(function (userPreferencesData) {
if (userPreferencesData.d.userId !== "")
{
sessionConfigurationService.setUserPreferences(userPreferencesData.d);
// $window.location.href = '/base.html';
}
});
}
});
});
};
My appKeyService factory is
app.factory('appKeyService', function ($q, authenticatedServiceFactory, configurationService) {
var deffered = $q.defer();
var service = {};
service.makeCall = function () {
debugAlert("appKeyService async method request start");
authenticatedServiceFactory.makeCall("GET", configurationService.getAppKeyURL(), "", "").then(function (data) {
debugAlert("appKeyService async method response")
deffered.resolve(data);
});
return deffered.promise;
};
return service;
});
My authenticated service factory is
app.factory('authenticatedServiceFactory', function ($http, $q, sessionConfigurationService) {
var deffered = $q.defer();
var service = {};
service.makeCall = function (methodType, URL, data, authType) {
var headerValue = "";
if (authType === "Basic") {
headerValue = sessionConfigurationService.getBasicToken();
} else if (authType === "Bearer") {
headerValue = sessionConfigurationService.getBearerToken();
}
var config = {headers: {
'Authorization': headerValue,
'Accept': 'application/json;odata=verbose',
},
withCredentials: true,
async: false
};
if (methodType === "GET") {
$http.get(URL, data, config)
.then(function (getData) {
debugAlert("GET method response" + JSON.stringify(getData));
deffered.resolve(getData.data);
}, function (error) {
debugAlert("GET method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "POST") {
$http.post(URL, data, config)
.then(function (putData) {
debugAlert("POST method response" + JSON.stringify(putData));
deffered.resolve(putData.data);
}, function (error) {
debugAlert("POST method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "DELETE") {
$http.delete(URL, data, config)
.then(function (deleteData) {
debugAlert("DELETE method response" + JSON.stringify(deleteData));
deffered.resolve(deleteData.data);
}, function (error) {
debugAlert("DELETE method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
else if (methodType === "PUT") {
$http.put(URL, config)
.then(function (putData) {
debugAlert("PUT method response" + JSON.stringify(putData));
deffered.resolve(putData.data);
}, function (error) {
debugAlert("PUT method response error" + JSON.stringify(error));
deffered.reject(error);
});
}
return deffered.promise;
};
return service;
});
But I don't see the service calls are made in sync. So the "then" part in the controller is not executing after we receive the response. Its executing one after the other. How can I make that happen.

#Frane Poljak
Thank you for your comment. I just brought
var deffered = $q.defer();
inside the makeCall method and its working as I wanted now. Thank you!
app.factory('appKeyService', function ($q, authenticatedServiceFactory, configurationService) {
var service = {};
service.makeCall = function () {
var deffered = $q.defer();
debugAlert("appKeyService async method request start");
authenticatedServiceFactory.makeCall("GET", configurationService.getAppKeyURL(), "", "").then(function (data) {
debugAlert("appKeyService async method response")
deffered.resolve(data);
});
return deffered.promise;
};
return service;
});

Related

Function is not recognized by another function in angularjs

During loading of the partial Html with controller, my function named $scope.actionViewVisitors() is recognized and runs without errors. But whenever I use it inside another function on the same controller, it gives me an error:
TypeError: $scope.actionViewVisitors is not a function. Please see my code below:
angular.module("Visitor.controller", [])
// ============== Controllers
.controller("viewVisitorController", function ($scope, $rootScope, $http, viewVisitorService, viewAccountService, DTOptionsBuilder) {
$scope.visitorList = null;
$scope.viewAccountDetail = null;
$scope.avatar = null;
$scope.visitorDetail = null;
$scope.visitorBtn = "Create";
$scope.actionViewAccount = function () {
$scope.actionViewAccount = viewAccountService.serviceViewAccount()
.then(function (response) {
$scope.viewAccountDetail = response.data.account;
$scope.avatar = "../../avatars/" + response.data.account.AccountId + ".jpg";
})
}
$scope.dtOptions = DTOptionsBuilder.newOptions()
.withDisplayLength(10)
.withOption('bLengthChange', false);
// THIS ONE IS NOT RECOGNIZED
$scope.actionViewVisitors = function () {
$scope.actionViewVisitors = viewVisitorService.serviceViewVisitors()
.then(function (response) {
debugger;
$scope.visitorList = response.data.visitorList;
});
}
// I DON'T GET ANY ERROR HERE
$scope.actionViewVisitors();
$scope.actionViewAccount();
$scope.createVisitor = function () {
$scope.statusMessage = null;
if ($scope.visitorBtn == "Create") {
$scope.createVisitor = viewVisitorService.serviceCreateVisitor($scope.visitorDetail)
.then(function (response) {
if (response.data.response == '1') {
bootbox.alert({
message: "Successfully created a new visitor.",
size: 'small',
classname: 'bb-alternate-modal'
});
} else if (response.data.response == '0') {
bootbox.alert({
message: "Failed in creting visitor.",
size: 'small',
classname: 'bb-alternate-modal'
});
}
});
debugger;
$scope.visitorDetail = undefined;
// I GET THE ERROR WHEN I CALL THIS METHOD
$scope.actionViewVisitors();
}
}
})
// ============== Factories
.factory("viewVisitorService", ["$http", function ($http) {
var fac = {};
fac.serviceViewVisitors = function () {
return $http({
url: '/Visitor/ViewVisitors',
method: 'get'
});
}
fac.serviceCreateVisitor = function(visitor) {
return $http({
url: '/Visitor/CreateVisitor',
data: { visitor: visitor },
method: 'post'
});
}
return fac;
}])
You are overwriting the function with Promise in the following line, thus the error is correct
$scope.actionViewVisitors = function () {
$scope.actionViewVisitors = viewVisitorService.serviceViewVisitors()
.then(function (response) {
$scope.visitorList = response.data.visitorList;
});
}
Remove $scope.actionViewVisitors =
$scope.actionViewVisitors = function () {
viewVisitorService.serviceViewVisitors()
.then(function (response) {
$scope.visitorList = response.data.visitorList;
});
}
On the first call to the function you are changing it from a function to a Promise. Maybe you want to be returning the result instead?
$scope.actionViewVisitors = function () {
return viewVisitorService.serviceViewVisitors()
.then(function (response) {
debugger;
$scope.visitorList = response.data.visitorList;
});
}

AngularJS $http.post/service issue

I have a weird problem.. when I am loading my details page, the error part gets executed first in the controller.
Though the service myService gets executed and it does return value, in the controller error is executed and I am not getting my message details.
I have put an alert in service before and jsonObj is valid.
controller:
url = 'http://' + add + ':8080/user/site.cgi';
data = {
ACTION : "list",
STATS : "no"
};
myService.getdata(url, data)
.then(function(data, status, headers, config) {
$timeout(function(){
if (data.body.response.status == "OK") {
if (data.body.response.msg.id) {
service2.seturl(data.body.response.msg.id, username, add);
messg.push(data.body.response.msg);
} else
angular.forEach(data.body.response.msg, function(value, key) {
service2.seturl(value.id, username, add);
messg.push(value);
})
$rootScope.messg = messg;
} else {
errorMessage = data.body.response.errmsg;
alert(errorMessage);
}
}, 5000);
}, function(error, status, headers, config) {
alert("Check network connection.."); //Coming here without fulfilling promise.
});
}
services:
.service('myService', function($http, $q, $httpParamSerializerJQLike) {
return {
getdata: function(url, data) {
var postData = data;
return $http({
method : 'POST',
url : url,
data : $httpParamSerializerJQLike(postData)
}).then(function(response, status, headers, config) {
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json(response.data);
if (typeof jsonObj === 'object') {
alert(jsonObj); //I am getting this alert just fine.
return jsonObj; //It does return the object.
} else {
return $q.reject(jsonObj);
}
}, function(response, status, headers, config) {
return $q.reject(response.data);
});
}
}
})
.factory('service2', function() {
var urls = [{ }];
return {
all: function() {
return urls;
},
geturl: function(id) {
for (var i = 0; i < urls.length; i++) {
if (urls[i].id === parseInt(id)) {
return urls[i];
}
}
return null;
},
seturl: function(id, admin, add) {
for (var i = 0; i < urls.length; i++) {
if (urls[i].id === parseInt(id)) {
return null;
}
}
var idInt = parseInt(id);
var createurl = 'http://' + add + ':8080/user/det.cgi';
var postData = {
ACTION : “add”,
LOGIN : admin
};
var url = {
id: idInt,
url: createurl,
data: postData
}
urls.push(url);
return null;
}
};
})
Try this , return a deferred promise
.service('myService', function($http, $q, $httpParamSerializerJQLike) {
return {
getdata: function(url, data) {
var deferred = $q.defer();
var postData = data;
$http({
method : 'POST',
url : url,
data : $httpParamSerializerJQLike(postData)
}).then(function(response, status, headers, config) {
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json(response.data);
if (typeof jsonObj === 'object') {
alert(jsonObj);
deferred.resolve(jsonObj);
} else {
deferred.reject(jsonObj);
}
}, function(response, status, headers, config) {
deferred.reject(response.data);
});
return deferred.promise;
}
}
})

How to return a boolean from an angular factory

I wrote a generic crud factory that is proving rather useful so far, the only problem is, when I go to use the service and check the result the value is not retaining the boolean true. I believe this is because javascript return acts on a per function basis, but I am not sure how to manuver the boolean out properly. Any ideas?
module.factory('crud', function ($http, API_CONFIG) {
return {
delete: function ($index, $scope, id, collection) {
$http({
url: API_CONFIG.url + collection + "/" + id,
method: 'DELETE',
headers: { "Content-Type": "application/json;charset=utf-8" }
}).success(function (result) {
console.log(result);
$scope.countries.splice($index, 1);
return true;
}).error(function () {
console.log("error");
});
},
update: function ($index, $scope, id, collection) {
console.log("update");
console.log(id);
console.log(collection);
},
create :function(model, collection) {
$http.post(
API_CONFIG.url + collection,
JSON.stringify(model),
{
headers: {
'Content-Type': 'application/json'
}
}
).success(function (data) {
console.log("model sent");
return true;
}).error(function () {
console.log("error");
});;
}
};
});
module.run(function ($rootScope, crud) {
$rootScope.appData = crud;
});
Then used like so in controller:
var result = $scope.appData.create(country, "collection");
if (result === true) {
You are using return inside a callback function that is asynchronous. Therefore the code that is executed afterwards should also by asynchronous. Try passing an additional function to create that will be executed on success. For example:
create: function(model, collection, callback) {
$http.post(...)
.success(function(data) { callback(data, true); })
.error(function(data) { callback(data, false); });
}
You can then use this like:
appData.create(model, collection, function(data, success) {
if(success === true) {
...
} else {
...
}
}
You need to return the promise return $http on the factory and them do something like this:
$scope.appData.create(country, "collection").then(function() {
// like a result = true;
}, function() {
// like a result = false;
});

How to re try operation after refresh token - jquery ajax

In my flow say i am using an access token for getting my data. When my access token expires i get a 401 error i am using the refresh token to get a new access token.
Note : My access token and refresh token is stored in a cookie and i am updating the same after a 401 error.
My question how do i retry the same operation which i was in the middle of?
My Code (services.js):
var refresh_token = "na";
function get_api_data(url, api_token) {
var returnData = handleApiData(url, api_token, "GET");
return returnData;
}
function post_api_data(url, api_token, post_data) {
var returnData = handleApiData(url, api_token, "PUT", post_data);
return returnData;
}
function handleApiData(url, access_token, type, post_data) {
return $.ajax({
url: url,
type: type,
data: post_data,
error: failHandler,
contentType: "application/json",
beforeSend: function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + access_token);
}
})
}
function handleData(data, textStatus, jqXHR) {
return data;
}
function failHandler(jqXHR, textStatus, errorThrown) {
switch (jqXHR.status) {
case 401:
var api = get_api_token();
checkApiToken(api.refresh_token);
break;
default:
alert(errorThrown);
}
}
function checkApiToken(refresh_token) {
if (refresh_token != "na") {
$.post("/Account/Refresh/?refresh_token=" + refresh_token);
//location.reload();
}
}
My Code (notification.js):
$(function () {
var api = get_api_token();
if (api != null)
get_notification_data(api.access_token);
});
function get_notification_data(api_token) {
var notifications = get_api_data(urls.notifications.list, api_token);
if (notifications != undefined)
notifications.success(function (data) {
items = data.records;
_.each(items, function (item) {
item.Status = ko.observable(item.status);
item.onClick = function () {
if (item.Status() === 'UNREAD') {
var post_data = { id: item.id };
post_api_data(urls.notifications.list, api_token, post_data).success(function (response, textStatus) {
if (response.success)
item.Status('READ');
$(location).attr("href", item.action_link);
});
}
else {
$(location).attr("href", item.action_link);
}
}
});
var model = {
items: ko.observableArray(items),
onCancel: function (item) {
}
}
ko.applyBindings(model, $("#notificationBar")[0]);
})
}
Edit: My AccountController code that sets the new API cookie:
[HttpPost]
public ActionResult Refresh(string refresh_token)
{
string token_string = string.Empty;
try
{
token_string = OAuthHelper.getTokenViaRefreshTokenFromAPIServer(refresh_token);
if(token_string != null)
Response.Cookies[Constants.Cookies.API].Value = token_string;
}
catch (Exception ex)
{
Log.Info(string.Format("AccountController.cs -Refresh Token Error ", ex.Message));
}
return RedirectToAction("Index","Home");
}

Getting 404 not found while creating new json file by Angular $resource

I created a service using ngResource to save the data of form in json format. But after submitting form I got 404 error for 999.json file.
ServiceJS
"use strict";
eventsApp.factory("eventData", function ($resource, $q) {
var resource = $resource("data/:id.json", {
id: "#id"
});
return {
getEvent: function () {
var deffered = $q.defer();
resource.get({
id: "event"
},
function (event) {
deffered.resolve(event);
},
function (status) {
deffered.reject(status);
});
return deffered.promise;
},
save: function (event) {
var deffered = $q.defer();
event.id = 999;
resource.save(event,
function (data, status, header, config) {
deffered.resolve(data);
},
function (data, status, header, config) {
deffered.reject(data);
}
);
return deffered.promise;
}
}
});
ControllerJS
eventsApp.controller('editEventCtrl', function ($scope, eventData) {
// Save Event
$scope.saveEvent = function (event, newEventForm) {
if (newEventForm.$valid) {
//alert("Event '" + event.ename + "' Saved Successfully !");
eventData.save(event)
.then(
function (response) {
console.log('Success ' + JSON.stringify(response));
},
function (response) {
console.log('Failure ' + JSON.stringify(response));
}
)
}
};
});
Please help me.

Categories