Reputation: 5795
I'm trying to chain some API calls before setting the textContent
of some spans
in my webpage. I can execute the following ajax API calls separately by pasting them into the console, but when I chain them as promises I get getFirstData() is undefined
.
var first_data = [],
second_data = [];
function getFirstData(){
var xhr = new XMLHttpRequest();
var url = "/API/first-data?format=json"
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
first_data = JSON.parse(xhr.responseText);
return Promise.resolve('1');
}
}
xhr.open("GET", url, true);
xhr.send();
}
/*getSecondData is the same, but with a different API url. I'll DRY these
two into one function that takes a url argument when I get it working.*/
getFirstData().then(getSecondData).then(createPage);
This is between <script>
tags just before </body>
. So what's wrong with the call to getFirstData()
on the last line that causes the interpreter to say it's undefined
? For reference, in the network log, getSecondData() is sent and returns just fine.
(Note: I'm specifically trying to do this without JQuery).
Upvotes: 0
Views: 116
Reputation: 3098
The issue occurs because your function is returning undefined
(in other words, getting to the end of the function block before it returns) before it ever gets a chance to return Promise.resolve('1')
.
Your function has to immediately return a Promise object, which becomes pending before eventually resolving inside your AJAX handler.
I'd also add error handling using the provided reject
argument, as is standard for Promise objects.
function getFirstData(){
return new Promise(function(resolve, reject) { // encapsulate code in a promise which returns immediately
var xhr = new XMLHttpRequest();
var url = "/echo/json"
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
first_data = JSON.parse(xhr.responseText);
return resolve('1');
}
else {
return reject('There was an error!') // reject the promise if error occurs
}
}
xhr.open("GET", url, true);
xhr.send();
});
}
And then catch it in the thenable chain:
getFirstData()
.then(getSecondData)
.catch(function(err){Throw err}) // catch the error if it throws
.then(createPage);
See working jsfiddle
Upvotes: 3
Reputation: 5890
getFirstData
isn't returning a promise it returns undefined
, which is not thenable.
function getFirstData(){
return new Promise(function(resolve) {
var xhr = new XMLHttpRequest();
var url = "/API/first-data?format=json"
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
first_data = JSON.parse(xhr.responseText);
resolve('1');
}
}
xhr.open("GET", url, true);
xhr.send();
});
}
Upvotes: 3