Working with small JavaScript apps for GNOME3 has led me to a wild exploration around internet, the quest for knowledge. The quest led me to trying to figure out two things – how to use different files from the same folder in your JavaScript app, and how to make asynchronous HTTP requests. I can tell the quest was a tricky one but now I can present you (queue dramatic music) my findings:
The first problem was brought up by wanting to separate asychronous calls to a different file. How can I reference the other file in my gjs code? The solution ended up being very simple. Just replace the normal gjs yourapp.js with this:
$ GJS_PATH=`pwd` gjs yourapp.js
in terminal in the folder your files are. Then the file can be included simply with:
const SomeClass = imports.myotherfile;
Where SomeClass is the variable that will hold any functions exported by the other file (by having those functions defined into the global namespace there), and myotherfile.js would be the name of the file.
You can see what keys are available through imports by running this JavaScript code through gjs:
for (i in imports) {
print(i);
}
If you want to distribute your files in different folders the GJS_PATH environment variable must contain the correct path.
As we see, pretty easy but hard to come by amongst all the information of internet. Maybe one more post about it will ease the search for the next person trying to figure this out 🙂
Then we get onwards with our asynchronous calls. HTTP get, using async libsoup. Yet again a simple thing but hard to find.
first you need to import Soup to your code:
const Soup = imports.gi.Soup;
then prepare one asynchronous soup session
const _httpSession = new Soup.SessionAsync();
Soup.Session.prototype.add_feature.call(_httpSession, new Soup.ProxyResolverDefault());
then you decide what you want to get and where. Here I’m getting weather information for Helsinki Malmi airport (ICAO: EFHF) using the GeoNames web service:
function getWeather(callback) {
var request = Soup.Message.new('GET',
'http://api.geonames.org/weatherIcaoJSON?ICAO=EFHF&username=demo');
Once you’ve prepared a request Soup message, you need to queue it, and provide a callback that will fire once the request has been handled.
It is good manners to handle both successful and failed requests. And when the information is in your hands, it is a good idea to parse it to proper JavaScript data structures:
_httpSession.queue_message(request, function(_httpSession, message) {
if (message.status_code !== 200) {
callback(message.status_code, null);
return;
}
var weatherJSON = request.response_body.data;
var weather = JSON.parse(weatherJSON);
callback(null, weather);
}
A successful response looks like this:
{
"weatherObservation": {
"clouds": "few clouds",
"weatherCondition": "light snow",
"observation": "EFHF 101150Z 14002KT 9999 -SN FEW040 BKN050 BKN070 M05/M06 Q1016",
"windDirection": 140,
"ICAO": "EFHF",
"elevation": 28,
"countryCode": "FI",
"lng": 25.05,
"temperature": "-5",
"dewPoint": "-6",
"windSpeed": "02",
"humidity": 92,
"stationName": "Helsinki-Malmi",
"datetime": "2012-01-10 11:50:00",
"lat": 60.25,
"hectoPascAltimeter": 1016
}
}
And then it is just the question of how to use the information.
This post has been updated according to Owen’s suggestions in the comments below.