No, this will not work. I will comment the relevant parts below.
Instead of having this in apiRequest
:
function apiRequest(search, lang) {
function resData(res) {
// ...
res.on('end', function () {
return JSON.parse(str); // Is this a right way to return data
});
// ...
}
https.get(options, resData).end();
}
and calling it with:
str = apiRequest(search, lang);
You should either pass a callback or return a promise.
Using callbacks
Your apiRequest
function can take an additional argument, a callback:
function apiRequest(search, lang, callback) {
function resData(res) {
// ...
res.on('end', function () {
callback(null, JSON.parse(str));
});
res.on('error', function(e) {
console.error(e);
callback(e);
});
// ...
}
https.get(options, resData).end();
}
Now you can use it as:
apiRequest(search, lang, function (error, str) {
if (err) {
// you have error
} else {
// you have your str here
}
});
Using promises
Your apiRequest
function can return a promise:
function apiRequest(search, lang, callback) {
return new Promise(function (resolve, reject) {
function resData(res) {
// ...
res.on('end', function () {
resolve(JSON.parse(str));
});
res.on('error', function(e) {
console.error(e);
reject(e);
});
// ...
}
https.get(options, resData).end();
}
}
Now you can use it as:
apiRequest(search, lang)
.then(function (str) {
// you have your str here
})
.catch(function (err) {
// you have error
});
This is not tested so there might be some minor mistakes but that is the general idea. When I find some errors I'll update the answer.
Summary
To sum it up, there are two styles that you can use to compose asynchronous functions like that: callbacks or promises. You will not be able to just return the data because return
is fundamentally synchronous - you have to have something to return right away - unless what you return is a promise that can get resolved or rejected later.
Parsing JSON
What should also keep in mind that you should always run JSON.parse()
inside a try {} catch {} block
to handle errors of incorrect JSON or otherwise the entire app could crash. JSON.parse()
throws exceptions on bad input. See this answer for more info.
This will additionally complicate your code but you can avoid that complication and make it even simpler by using the request
module - see updates below.
Simpler examples
Callbacks
To have a working example that is simpler and your don't have to manually parse JSON, consider this code that I just wrote, based on your example but calling a GitHub API so it can be tested by everyone - it prints someone's website given his GitHub nickname but otherwise works similarly to your code:
'use strict';
var request = require('request');
function apiRequest(search, callback) {
var options = {
url: 'https://api.github.com/users/' + search,
json: true,
headers: {'User-Agent': 'request'}
};
function resData(err, res, data) {
if (err) {
callback(err);
} else if (res.statusCode !== 200) {
callback(res.statusCode);
} else {
// data is already parsed as JSON:
callback(null, data.blog);
}
}
request.get(options, resData);
}
apiRequest('rsp', function (err, data) {
if (err) {
console.log('Error:', err);
} else {
console.log('Data:', data);
}
});
This is an example using callbacks.
Promises
And here is an example using promises:
'use strict';
var request = require('request');
function apiRequest(search, callback) {
return new Promise(function (resolve, reject) {
var options = {
url: 'https://api.github.com/users/' + search,
json: true,
headers: {'User-Agent': 'request'}
};
function resData(err, res, data) {
if (err) {
reject(err);
} else if (res.statusCode !== 200) {
reject(res.statusCode);
} else {
// data is already parsed as JSON:
resolve(data.blog);
}
}
request.get(options, resData);
});
}
apiRequest('rsp')
.then(function (data) {
console.log('Data:', data);
})
.catch(function (err) {
console.log('Error:', err);
});
Simplified
It can be simplified even further by using fat arrow functions and anonymous functions and object literals:
'use strict';
var request = require('request');
function apiRequest(search, callback) {
return new Promise((resolve, reject) => {
request.get({
url: 'https://api.github.com/users/' + search,
json: true,
headers: {'User-Agent': 'request'}
}, (err, res, data) => {
if (err) {
reject(err);
} else if (res.statusCode !== 200) {
reject(res.statusCode);
} else {
resolve(data.blog);
}
});
});
}
apiRequest('rsp')
.then(data => console.log('Data:', data))
.catch(err => console.log('Error:', err));
More info
You can see some other answers where I explain the difference between callbacks and promises and how to use the together in more detail, which you may find helpful: