How to call function itself inside a function in my case - javascript

I am trying to call the function itself within the function.
Basically it will call the function itself to make another request if the first request has the id.
I have something like
function test(variable) {
var q = $q.defer();
$http({
method: 'get',
url: 'myurl.com'
}).then(function(returnData) {
if(returnData.getNewInfo) {
test(returnData.id).then(function(secondData){
q.resolve(secondData);
})
} else {
q.resolve(returnData)
}
});
}
return q.promise;
}
I am getting
test(...).then is not a function error in the console on this line
test(returnData.id).then(function(secondData){
I am trying to call the function itself inside the promise. Not sure how to fix my issue. Can anyone help me about it? Thanks a lot!

Fix your code indentation and you'll get the below - see my comment about the stray brace. So the function is returning undefined rather than q.promise.
function test(variable) {
var q = $q.defer();
$http({
method: 'get',
url: 'myurl.com'
}).then(function(returnData) {
if (returnData.getNewInfo) {
test(returnData.id).then(function(secondData) {
q.resolve(secondData);
})
} else {
q.resolve(returnData)
}
});
} // <------- end of function - should be removed?
return q.promise;
}

You can return your $http call. Promises are chainable and $http returns a promise.
function test(variable) {
return $http({
method: 'get',
url: 'myurl.com'
}).then(function (returnData) {
if (returnData.getNewInfo) {
return test(returnData.id);
} else {
return returnData;
}
});
}

Try this:
function test(variable, callback) {
/*snip*/
callback();
/*snip*/
}
test("foo",test);

Related

Return callback value outside callback function (ajax)

I am trying return callback value outside callback function example:
I make the function based in topic: How do I return the response from an asynchronous call?
(function (){
return getAjaxResult(function(result) { return result; });
//<-- Return Undefined (in console log return correct value)
})();
function getAjaxResult(callback){
$.ajax({
url: 'myurl',
type: 'GET',
success: function (result)
{
if (result === 'working'){
callback(result);
}else if (result === 'notworking'){
callback('notworking');
}
}
})
}
Return "Undefined" (in console log return correct value).
I do not know if this is the best option to return an ajax value in callback
There are two ways to do this, you can use async false but is deprecated and you can always use a promise:
do a function like this:
function ajaxCallback(id){
return $.ajax({
method: "POST",
url: "../YourUrl",
data: { id: id}
})
}
then call it like this:
if (id != '')//
{
ajaxCallback(id)
.done(function( response ) {
//do something with your response
});
}
Hope it helps

is it possible not to execute the promise (.then ()) in the controller when there is an error in a web request?

I'm currently using a factory called http that when I invoke it, I make a web request. this receives as a parameter the url of the web request.
app.factory('http', function ($http) {
var oHttp = {}
oHttp.getData= function (url) {
var config={
method: 'GET',
url: url
}
return $http(config).then(function(data) {
oHttp.data=data.data;
},function(response) {
alert("problem, can you trying later please?")
});
}
return oHttp;
});
function HelloCtrl($scope, http) {
http.getData('https://www.reddit.com/.json1').then(function(){
if(http.data!=undefined){
console.log(http.data)
}
})
}
I would like the promise not to be executed on the controller if the result of the web request is not satisfied or there is a problem. is there any better solution? I want to avoid doing this every time I make a web request, or do not know if it is the best way (see the if):
//I am putting "1" to the end of the url to generate an error.
http.getData('https://www.reddit.com/.json1').then(function(){
//validate that the result of the request != undefined
if(http.data!=undefined){
alert(http.data.kind)
}
})
In my real project I make n web requests using my factory http, I do not want to do this validation always. I do not know if I always have to do it or there is another solution.
this is my code:
https://plnkr.co/edit/8ZqsgcUIzLAaI9Vd2awR?p=preview
In rejection handlers it is important to re-throw the error response. Otherwise the rejected promise is converted to a successful promise:
app.factory('http', function ($http) {
var oHttp= {};
oHttp.getData= function (url) {
var config={
method: 'GET',
url: url
}
return $http(config).then(function(response) {
̶o̶H̶t̶t̶p̶.̶d̶a̶t̶a̶=̶r̶e̶s̶p̶o̶n̶s̶e̶.̶d̶a̶t̶a̶;̶
return response.data;
},function(response) {
alert("problem, can you trying later please?")
//IMPORTANT re-throw error
throw response;
});
}
return oHttp;
});
In the controller:
http.getData('https://www.reddit.com/.json1')
.then(function(data){
console(data)
}).catch(response) {
console.log("ERROR: ", response.status);
});
For more information, see You're Missing the Point of Promises.
In Service
app.factory('http', function ($http) {
var oHttp = {}
oHttp.getData= function () {
return $http({
method: 'GET',
url: 'https://www.reddit.com/.json1'
});
}
return oHttp;
});
In controller
function HelloCtrl($scope, http) {
var httpPromise = http.getData();
httpPromise.then(function(response){
console.log(response);
});
httpPromise.error(function(){
})
}
So I tried this in codepen having ripped your code out of plinkr
https://codepen.io/PocketNinjaDesign/pen/oGOeYe
The code wouldn't work at all...But I changed the function HelloCtrl to a controller and it seemed happier....?
I also set response.data to default to an empty object as well. So that way if you're populating the data in the page it will be empty if nothing arrived. You can then in some instances on the site check the length if it's really required.
app.factory('http', function ($http) {
var oHttp = {}
oHttp.data = {};
oHttp.getData= function (url) {
var config = {
method: 'GET',
url: url
}
return $http(config).then(function(response) {
oHttp.data = response.data || {};
}, function(response) {
alert("problem, can you trying later please?")
});
}
return oHttp;
});
app.controller('HelloCtrl', function($scope, http) {
http.getData('https://www.reddit.com/.json').then(function(){
alert(http.data.kind);
})
});

Promise Angularjs 1.6 How can I force function to wait for api response

Im using this plugin: http://www.codingdrama.com/bootstrap-markdown/
I want to hook the onPreview
So on onPreview i try to make my api call:
app.directive("markdowntextarea",function ($http, $q) { // inject $q
return {
link: function (el_scope, element, attr) {
element.markdown(
{
autofocus: false,
savable: false,
onPreview: function (e) {
var deferred = $q.defer();
if (e.isDirty()) {
var originalContent = e.getContent();
$http({
url: '/api/markdown/',
data: {"body": originalContent, "actual_format": "md"},
method: 'POST'
}).then(function successCallback(response) {
console.log("successCallback", response.data.content);
deferred.resolve(response.data.content);
}, function errorCallback(response) {
console.log("errorCallback");
deferred.reject("error");
});
} else {
deferred.resolve("");
}
return deferred.promise;
}
}
);
}
}
});
Console:
successCallback from api!!!
I got success response from api, the response.data.content is what I want to use. The problem here is the return deferred.promise; always return the original value. What can I do here? I'm really new in angularjs
With promises you can't return values at once, usually you return promise object called promise handle and using 'then' clause you wait for promise to resolve(successfully) or reject(failure).
In your case if you want to wait for response and then do something I suggest you call onPreview and use its then clause like:
onPreview(e).then(function(response){}, function(error){});
onPreview is already returning promise which should be thenable.
After Edit:
So onPreview is API method and is expecting a text not promise, now what you can do is define a function like makePreview or something:
function makePreview(e) {
var deferred = $q.defer();
if (e.isDirty()) {
var originalContent = e.getContent();
$http({
url: '/api/markdown/',
data: {"body": originalContent, "actual_format": "md"},
method: 'POST'
}).then(function successCallback(response) {
console.log("successCallback", response.data.content);
deferred.resolve(response.config.data.body);
}, function errorCallback(response) {
console.log("errorCallback");
deferred.reject("error");
});
} else {
deferred.resolve("");
}
return deferred.promise;
}
and then your onPreview should look like this:
autofocus: false,
savable: false,
onPreview: function (e) {
makePreview(e).then(function(response){
e.setContent(response);
return response;
}, function(error){
return error;
});
}
I hope this helps :)
You cannot write angular in absolute sync way. Use the response in callback.
If you need to control api requests' order, or wait for multiple requests, see doc of $q

How to replace 'Async=false' with promise in javascript?

I have read a lot about promises but I'm still not sure how to implement it.
I wrote the folowing AJAX call with async=false in order for it to work, but I want to replace it with promise as I saw that async=false is deprecated.
self.getBalance = function (order) {
var balance;
$.ajax({
url: "/API/balance/" + order,
type: "GET",
async: false,
success: function (data) {
balance = data;
},
done: function (date) {
}
});
return balance;
}
Would you be able to help me? I just need an example to understand it.
As first point, you don't want to set an asynchronous call to false as it will lock the UI.
You could simplify your method returning the ajax object and the handle it as a promise.
self.getBalance = function (orderNumber) {
return $.ajax({
url: "/Exchange.API/accountInfo/balance/" + orderNumber,
type: "GET",
});
};
var demoNumber = 12;
self.getBalance(demoNumber).then(function(data){
console.log(data);
},function(err){
console.log("An error ocurred");
console.log(err);
});
Return promise object from getBalance method:
self.getBalance = function (orderNumber) {
return $.ajax({
url: "/Exchange.API/accountInfo/balance/" + orderNumber,
type: "GET"
});
}
and use it later like this:
service.getBalance().then(function(balance) {
// use balance here
});

Data from $resource not synchronized to call from HTML

I'm able to get the print the array returned inside vm.getProduct() in the controller. But this not available in HTML.
Resource:
var DataProvider = function ($resource) {
return $resource('', {}, {
getProductTypeAhead: {
method: 'GET',
isArray: true,
url: '/productinterface?typeahead=:typeAhead',
params: {typeAhead: '#typeAhead'}
}
});
};
module.exports = ['$resource', DataProvider];
Service:
var DataService = function (DataProvider, $scope) {
this.getProductTypeAhead = function (typeAhead, callback) {
DataProvider.getProductTypeAhead({typeAhead: typeAhead},
function (data) {
callback(data);
}, function (data) {
// NOTIFY THE USER THAT THE REQUEST FAILED
callback(null);
});
};
};
module.exports = ['DataProvider', DataService];
Controller:
vm.getProduct = function ($viewValue) {
return DataService.getProductTypeAhead($viewValue, function (response) {
console.log(response);
return cleanResponse(response);
});
};
function cleanResponse(response) {
return JSON.parse(global.angular.toJson(response));
}
HTML:
<input type="text" class="form-control" id="product"
typeahead-min-length="3"
typeahead="product as product.legalName for product in vm.getProduct($viewValue)"
typeahead-template-url="app/main/templates/typeahead-ProductInterface-Template.html"
ng-model="vm.trade.PRODUCT_NAME">
However, if I go for $http.get() approach, I'm able to see the array in HTML.
vm.getProduct1 = function ($viewValue) {
return $http.get('/productinterface?typeahead=' + $viewValue).then(function (response) {
console.log(response.data);
return response.data;
});
};
I checked for the posts to synchronize $resource calls. No luck in that front.
Any pointers on this issue will be much appreciated.
TIA,
Bhushan
If you wanna use $resource with typeahead you can't use the normal callbacks. You need to return a promise.
Return a promise of a $resource request:
vm.getProduct = function ($viewValue) {
return DataService.getProductTypeAhead($viewValue, function (response) {
return response;
}).$promise;
};
Return a promise of a $resource request with callback;
vm.getProduct = function ($viewValue) {
return DataService.getProductTypeAhead($viewValue)
.$promise.then(function(response) {
return doSomethingWith(response);
});
});
};
See example - Asynchronous results
You are returning a promise not the value. That is vm.getProduct is a funciton that returns a promise not data.
vm.getProduct = function ($viewValue) {
return DataService.getProductTypeAhead($viewValue, function (response) {
console.log(response);
return cleanResponse(response);
});
};
function cleanResponse(response) {
return JSON.parse(global.angular.toJson(response));
}
You should set it to any vm property like this
vm.getProduct = function ($viewValue) {
return DataService.getProductTypeAhead($viewValue, function (response) {
console.log(response);
vm.myProperty = cleanResponse(response);
return cleanResponse(response);
});
};

Categories

Resources