Reputation: 63
I just heard about promises and it sounds... promising (ok I'm leaving).
I would expect the following code to show:
- before initVariables
- before initVariables
- someName
- before initVariables
- someName
- after initElements
But instead I got:
- before initVariables
- before initVariables
- before initVariables
- after initElements
Anybody to help me? :-)
Thx all! :D
var url = "https://opendata.paris.fr/api/records/1.0/search/?dataset=stations-velib-disponibilites-en-temps-reel&rows=100&facet=banking&facet=bonus&facet=status&facet=contract_name"
var test = Object.create(MyTestClass);
console.log(test.testVariable);
let loadVariables = new Promise(function(resolve, reject) {
test.initVariables(url);
resolve(test);
console.log(test.testVariable);
});
loadVariables.then(function(test){
test.initElements();
});
console.log(test.testVariable);
And MyTestClass
is defined by:
var MyTestClass = {
testVariable: "before initVariables",
initVariables: function(url) {
$.getJSON(url, function (result) {
this.testVariable += " - " + result.records[0].fields.name;
});
},
initElements: function() {
this.testVariable += " - after initElements";
}
}
Upvotes: 0
Views: 1354
Reputation: 19301
To explain the observed result, the expected result is missing the effect of asynchronous actions. Here are some rules that may help:
Promise executor functions are called synchronously when a new promise is created. When execution continues after a new Promise( executor)
statement or expression, the executor function has returned.
Promise reaction handlers, supplied by calling then
or catch
methods on a promise, are executed asynchronously, in a thread of their own, after the promise they were called on becomes settled.
Assume that the $.getJSON
request makes a call back asynchronously after a HTTP GET operation has taken place.
Walking through the code:
//** The top of code executing in a thread, say "T1":
var url = "https://www.example.com"
var test = Object.create(MyTestClass);
//** here test.testVariable inherits "before initVariables"
console.log(test.testVariable);
let loadVariables = new Promise(function(resolve, reject) {
test.initVariables(url);
//** here an asynchronous $getJSON request has been initiated but not completed
resolve(test);
//** here the Promise has been synchronously fulfilled,
//** during execution of this executor function, with the test object.
console.log(test.testVariable);
//** here test.testVariable inherits "before initVariables"
//** because we are still running synchronously in thread "T1" from the top.
});
loadVariables.then(function(test){
test.initElements();
//** this is some time later, not in thread "T1", because
//** then and catch callbacks are made asynchronously.
});
console.log(test.testVariable);
// here thread "T1" is still executing,
// testVariable has not been updated yet.
Note that synchronously fulfilling the created promise with the test
object was not useful in the end. Waiting for the GET request to call back with result data requires reconsideration of the approach to take.
Upvotes: 0
Reputation: 1
Promise
constructor is not necessary, as $.getJSON()
returns a jQuery promise object which exposes .then
function.
$.getJSON()
is not returned from function at javascript
at Question. this
is jqxhr
jQuery promise object unless set at context
of $.ajax()
calls. You can use Function.prototype.bind()
or $.proxy()
to set this
at .then()
chained to test.initVariables
, where $.getJSON(url)
call is returned from function.
var MyTestClass = {
testVariable: "before initVariables",
initVariables: function(url) {
return $.getJSON(url)
},
handleResult: function(result) {
this.testVariable += " - " + result.records[0].fields.name;
console.log(this.testVariable);
},
initElements: function() {
this.testVariable += " - after initElements";
console.log(this.testVariable)
}
}
var url = "https://opendata.paris.fr/api/records/1.0/search/?dataset=stations-velib-disponibilites-en-temps-reel&rows=100&facet=banking&facet=bonus&facet=status&facet=contract_name";
var test = Object.create(MyTestClass);
console.log(test.testVariable);
var loadVariables = test.initVariables(url);
loadVariables
.then($.proxy(test.handleResult, test))
.then($.proxy(test.initElements, test))
.fail(function(jqxhr, textStatus, errorThrown) {
console.log(textStatus, errorThrown);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
Upvotes: 0
Reputation:
Promises run immediately. The only way they don't resolve/reject immediately is if you do something inside them (like call $.getJSON
) and only call resolve/reject
based on the callback from $.getJSON
.
function getJSONP(url) {
return new Promise(function(resolve, reject) {
$.getJSON(url, resolve);
}
}
or
function getJSONP(url) {
return new Promise(function(resolve, reject) {
$.getJSON(url, function(result) {
resolve(result);
});
}
}
It that makes it clearer
You can then do
getJSONP(someURL).then(function(result) {
console.log(result);
});
Upvotes: 4