Reputation: 1154
I am new to NodeJS and I am working on a request.get
problem. My goal is simply have a function that request the web, and when request finished, the function returns the result, otherwise it returns an error message.
Here's the function that I used for request:
var artistNameIdMap = {};
var getPopularArtists = async () => {
//https://nodejs.org/api/http.html#http_http_request_options_callback
var options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
json: true
}
request.get(options, function(error, response, body) {
if (response.statusCode === 200){
console.log("inside");
artistNameIdMap = getArtistNameIdMap(body, artistNameIdMap);
} else {
res.send("get popular error");
return {};
}
})
console.log("outside");
return artistNameIdMap;
module.exports = {
GetPopularArtists: getPopularArtists
}
And this function is included in a getPopular.js
file. I would like to call the function in another file playlist.js
.
In playlist.js
, I wrote
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", (req, res) =>{
const artistNameIdMap = getPopular.GetPopularArtists();
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
})
However the result I got is
outside
Promise { {} }
inside
It seems like the return was before the request gives back the information. I wonder what should I write to make sure that I can obtain the correct artistNameIdMap
at playlist.js
.
Upvotes: 0
Views: 1620
Reputation: 707298
Though you've already accepted an answer, there are a couple of additional things I can add. First, the request()
library has been deprecated and it is not recommended for new code. Second, there is a list of recommended alternatives here. Third, all these alternatives support promises natively as that is the preferred way to program asynchronous code in modern nodejs programming.
My favorite alternative is got() because I find it's interface simple and clean to use and it has the features I need. Here's how much simpler your code would be using got()
:
const got = require('got');
let artistNameIdMap = {};
async function getPopularArtists() {
const options = {
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
};
const url = CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath;
let results = await got(url, options).json();
// update local cache object
artistNameIdMap = getArtistNameIdMap(results, artistNameIdMap);
return artistNameIdMap;
}
module.exports = {
GetPopularArtists: getPopularArtists
}
Note: The caller should supply error handling based on the returned promise.
GetPopularArtists().then(results => {
console.log(results);
}).catch(err => {
console.log(err);
});
Upvotes: 1
Reputation: 6264
Since you want to use Promises, use it like this
const getPopularArtists = () => new Promise((resolve, reject) {
const options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: {
'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
json: true
}
request.get(options, (error, response, body) => {
if (error) {
reject(error);
} else if (response.statusCode === 200) {
console.log("inside");
resolve(getArtistNameIdMap(body, artistNameIdMap));
} else {
reject("get popular error");
}
});
});
module.exports = {
GetPopularArtists: getPopularArtists
}
And use it like
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", async (req, res) =>{
try {
const artistNameIdMap = await getPopular.GetPopularArtists();
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
} catch(err) {
res.send(err);
}
})
Alternatively, without promises, you'll need to use a callback
Using callbacks:
const getPopularArtists = (callback) => {
const options = {
url: CONSTANTS.API_ENDPOINTS.playlist_endpoint + subpath,
headers: { 'Authorization': 'Bearer ' + access_token,
'Accept': 'application/json',
'Content-Type': 'application/json'},
json: true
}
request.get(options, function(error, response, body) {
if (error) {
callback(error);
} else if (response.statusCode === 200){
console.log("inside");
callback(null, getArtistNameIdMap(body, artistNameIdMap));
} else {
callback("get popular error");
}
})
};
module.exports = {
GetPopularArtists: getPopularArtists
}
And use it like:
const getPopular = require('./controllers/getPopular');
router.get("/BPM/:BPM", (req, res) =>{
getPopular.GetPopularArtists((err, artistNameIdMap) => {
if (err) {
// handle error here
} else {
console.log(artistNameIdMap);
let BPM = req.params.BPM;
res.send(BPM);
}
});
});
Upvotes: 1