Javascript: .then() in promise is not executing? - javascript

I want a script file just for accessing a JSON from a url. I want to have a method to return the JSON object from the script into a var in a separate script file then modify it accordingly. Obviously since javascript is asynchronous it fails if I simply write it out. Therefore I must use a promise:
var promise1 = new Promise(function(resolve, reject) {
access(userSearchText); //send user input to get appropriate JSON object
});
promise1.then(function(value) {
var getData = returnData(); //method that returns JSON object from the other script
alert(getData); //print out the returned JSON object
console.log("we have finished");
});
But this is not printing out anything. The alert does not occur at all and nothing is being printed in the console. I am using jquery to access the url in the other script and I have a .done after accessing it in the script for retrieving the JSON as: access.js
var sendData;
(function() {
jqxhr = $.getJSON( url, {
})
.done(function( data ) {
sendData = data;
});
})();
function returnData(){
return sendData;
}
So there should not be any asynchronous issues in the script for accessing the URL because of .done. I really don't understand why this isn't working. I inspected my page and there are no errors to be seen anywhere. Can anyone help?

promise1 never gets resolved.
In your definition of promise1, you never call the resolve() function to resolve it. Thus, it's .then() never gets called.
Manually created promises are only resolved when you explicitly call resolve() in the executor function.
If access() is itself asynchronous, then we will need to more about that function to help you do this correct. Wrapping a promise around it does not do anything to help you. If access() itself returns a promise, you should just use that promise and not wrap one around it.
Probably access() should return a promise that is resolved when it's asynchronous operation is done and then you can do:
access().then(...).catch(...);
And, not wrap it with another promise.
The sendData and returnData() stuff just looks wrong. You'd have to explain and show more context to know what exactly the recommend.

Related

JavaScript not delivering promise

I have two functions. function1() takes more time to complete than function2() because it does a fetch request. I need them to be launched in this order, but the results of function2() are the first that are displayed on the HTML DOM. So, I tried to resolve this with promises. I made the first function a variable, and created the following code:
let promise1 = function1() {
fetch()
.then(do x)
.then(display x to HTML DOM)
return 0;
};
function2(a) {
// use the a;
// display some things to the HTML DOM based on `a`
}
promise1.then((a) => {
function2(a);
});
Originally, these two functions don't need to interact with one another, but in order to make this work with promises, I created an artificial need by using that return statement. However, this doesn't work: I get a TypeError: promise1.then is not a function error. I skimmed through the 'Learn more' webpage, but those scenarios don't apply here.
I am quite new to JS and a neophyte to promises. Am I missing something?
You just need to return the promise returned from fetch in your first code block:
let promise1 = function1() {
return fetch()
.then(do x)
.then(() => {
//returns also need to be async
return 0;
});
//don't do this
// return 0;
// return inside the then() above
};
function2(a) {
// use the a;
// display some things to the HTML DOM based on `a`
}
promise1.then((a) => {
function2(a);
});
To explain this in greater detail; Your fetch runs async. So any subsequent functions will not wait (block). fetch returns a Promise that allows you to chain subsequent functions when the async function finishes. So to run anything after fetch you need to consume the Promise that fetch returns. then is a function of the Promise object, not fetch itself, to consume the promise (call then on the promise object) you need to return it first, hence return fetch().... How do I return the response from an asynchronous call? goes into this in detail
To address this, you will need to ensure function1 returns a promise object.
By returning a promise object, this allows you to "chain" subsequent .then() handlers off of calls to that function (ie promise1) as you are trying to do.
So in the case of your specific problem, you would want to do something like this:
let promise1 = function1() {
return fetch('/some/url').then(function (response){
// Do response processing logic here
return response;
}).then(function (data) {
//Chain any other data/response processing
return data;
});
};
The key thing to remember here is to return the call to fetch, as well as return data in each then handler that you chain to the call to fetch.
Hope that helps!

Get the result inside an object is coming from ajax using getJson

Guys I try access and save the data is coming from ajax using getJson I have some like this
var conversation
conversation = $.getJSON("http://myapi&jsonp=?", function (response) {
return response;
});
console.log(conversation)
I get in my console this
I getting my data inside of responseJSON so I try do some like this
conversation.responseJSON.DATA
but this is give to me undefined what am I doing wrong ? can some one help me pleases
$.getJSON is an asynchronous call, that means that it doesn't get the results instantly, it make a call to the server and the results are available to the the callback function.
You need to put all the code that accesses the results returned from the server inside your callback function
function (response) {
// this is where your code goes.
}
In your code above the variable conversation is a promise, you don't get the results from the promise but with the callback function that runs when the promise resolves.
The usual way of access a promise is with a then call.
var conversationPromise = $.getJSON("http://myapi&jsonp=?");
conversationPromise.then(function(results) {
// Here is where your results are available.
});

Asynchronous jquery - ajax when().then();

I have been trying to read the documents, but I'm having a hard time understanding some concepts:
$.when(function(){
$.ajax({url:'php/Mostrarphp.php', type:'post',data: {queHacer:"MostrarUsuarios"}})
.then(function(success) {
$("#main").html(success);
},function(error) {
$("#main").html(error);
});
})
.then(function() {
console.log("test");
});
What I'm trying to do is for the first function to go into the PHP file and inside that file there is only an include to another file. After that I want to have a console log shown. (This is just practice for, when I need to run functions that retrieve data and will take longer).
The issue here is that the echo is not showing on the application, only shows what is resolved on the then (console.log("test")).
What is the correct way to have this execute the inside function and then the second one?
When you use $.when, you are creating a new promise, one that needs to be resolved. Normally, $.when is used to "combine" multiple promises into one and then run a function once all of them resolve.
What you've passed to $.when is just a function. A function that never gets run. From the docs:
If a single argument is passed to jQuery.when() and it is not a Deferred or a Promise, it will be treated as a resolved Deferred and any doneCallbacks attached will be executed immediately.
So, that means your console.log("test"); is ran, but your AJAX code is never ran.
You do not not to use $.when here. $.ajax already returns a promise, there's no need to make another one. You can just chain .then() calls.
$.ajax({
url:'php/Mostrarphp.php',
type:'post',
data: {queHacer:"MostrarUsuarios"}
}).then(function(success){
$("#main").html(success);
},function(error){
$("#main").html(error);
}).then(function(){
console.log("test");
});
EDIT: In the comments you said:
[no] matter how much time the inside execution takes to complete, the outside [should] always execute second
If this is what you want, then you will need to create another promise. You can do that and then have it resolve once your "inside" function is complete. I'd suggest wrapping your AJAX code in a function and having it return a promise that you can attach a callback to.
function ajaxCall(){
var d = new $.Deferred;
$.ajax({
url:'php/Mostrarphp.php',
type:'post',
data: {queHacer:"MostrarUsuarios"}
}).then(function(success){
setTimeout(function(){
$("#main").html(success);
d.resolve();
}, 2000);
},function(error){
$("#main").html(error);
d.reject();
});
return d.promise();
}
ajaxCall().then(function(){
console.log("test");
});

AngularJS promise not working

I have a promise that runs without a problem when it runs during application start, e.g.
myPromise
.success( function(data) { $scope.myvariable = data })
.error( function(msg, code) { console.log("msg: " + msg + "\nCode" + code) });
However if I try to run the promise dynamically, let's say when a button is clicked, (1) the promise executes successfully but none of my variables are updated.
running apply or digest only produces the following error: $digest already in progress
$scope.getContent = function() {
myPromise
.success( function(data) {
$scope.myVariable = data; //THIS WORKS
console.log(data); //THIS WORKS
})
}
//Running the below code afterwards still produces a null value
console.log($scope.myVariable);
This is what we called as async world.
When you are waiting for the callback of your promise the statement console.log($scope.myVariable); already executed but still you don't have any value in it.
In that case you can use $watch if you want to get it value outside.
$scope.$watch('myVariable',funciton(newVal){
console.log(newVal);
});
Little Detail:-
myPromise is invoked and waiting for the response in the meanwhile the statement console.log($scope.myVariable); after it executed which obviously doen't have any value for $scope.myVariable inside it (nobody gave it :-P). So when response came back it call the success or error method and initialize the value to your variable $scope.myVariable and print it.
Here your console.log($scope.myVariable); statement executes before success callback so here you need to do .then() chaining or apply watch on scope variable.
The reason your console.log, which comes after your promise logs null is because it is executing before your promise returns. Even though the function using the promise has run, the success part of the code has not fired yet. The code hits the promise, makes the calls, creates the promise object, and moves on. When the promise returns, it fills in the empty promise object with the returned data. This is happening after your
console.log($scope.myVariable);
A good way maybe to handle it is to store the returned value in a variable. Inside the success set the variable to the returned data, then use a function like
$scope.myVariable = undefined;
$scope.getContent = function() {
myPromise
.success( function(data) {
$scope.myVariable = data; //THIS WORKS
console.log(data); //THIS WORKS
})
}
function checker() {
if($scope.myVariable) {
console.log($scope.myVariable);
}
}
Then you can call that function as needed.
Depending on what you are doing and when your getContent function needs to run, you may want to use this with ui-router, and use resolve, which will run these functions before the page loads, thereby ensuring you have data to work with when the DOM loads.
AngularJS UI-Router: preload $http data before app loads
I think promise object makes call only once,when controller is initialized
you have to reinitialize controller,to get new updated values from server
A. Call sequence will be as follows when DOM ready:
1. $scope.getContent will get initialized.
2. then execution : console.log($scope.myVariable);
B. Async call:
1. If success then below statement will get executed.
$scope.myVariable = data; //THIS WORKS
Above point A and B are independent. Execution is asyc here.
Hope this will help you understand. Enjoy.
Maybe this can help :
// a service providing data with async call
app.service('myService', function(elasticQuery) {
this.getData = function (a,b,c) {
// don't forget the 2 return
return elasticQuery.search({
// make ajax call
}).then(function (response) {
return response
});
};
});
// in my controller
// scope.getData is lunch with ng-click in the view
$scope.getData = function(a,b,c){
myService.getData( a,b,c ).then(function (data) {
$scope.myVariable = data;
});
};

How to correctly chain promises in complex resource loading sequence?

In angular code, I have a chained promise like this:
// a function in LoaderService module.
var ensureTypesLoaded= function(){
return loadContainerTypes($scope).then(loadSampleTypes($scope)).then(loadProjectList($scope)).then(loadSubjectTypes($scope));
}
Each of these functions return a promise, that loads things from a resource and additionally modifies $scope on error and success, e.g.:
var loadProjectList = function ($scope) {
// getAll calls inside a resource method and returns promise.
return ProjectService.getAll().then(
function (items) {
// succesfull load
console.log("Promise 1 resolved");
$scope.projectList = items;
}, function () {
// Error happened
CommonService.setStatus($scope, 'Error!');
});
};
I intent to use in in a code in a controller initialziation as such:
// Part of page's controller initialization code
LoaderService.ensureTypesLoaded($scope).then(function () {
// do something to scope when successes
console.log("I will do something here after all promises resolve");
}, function () {
// do something when error
});
However, this does not work as I'd like to. Ideally message "I will do something here after all promises resolve" must appear after all promises resolve. Instead, I can see that it appears earlier than messages from resolved promises within functions that are listed ensureTypesLoaded.
I would like to create a function ensureTypesLoaded such, that:
it returns a promise that is resolved when all chained loads are resolved;
if any of "internal" promises fail, the function should not proceed to next call, but return rejected promise.
obviously, if I call ensureTypesLoaded().then(...), the things in then() must be called after everything inside ensureTypesLoaded is resolved.
Please help me with correct building of chained promises.
I thinks that problem is in your loadProjectList function. Because .then() should receive function which is called at resultion time. Usually is function returning chain promise.
But in your case you call all load immediately in parallel. It's little complicated with $scope passing. But I think your code should appear like this
//this fn is called immediatly on chain creation
var loadProjectList = function ($scope) {
//this fn is called when previous promise resolves
return function(data) {
//don't add error handling here
ProjectService.getAll().then(...)
}
}
This cause serial loading as you probably want. (just notice: for parallel excution in correct way $q.all is used)
Finally you should have error handler only in ensureTypesLoaded, not in each promise.

Categories