Vaia Vaia - 4 months ago 11
Javascript Question

Save Wikipedia text in English if German not available with $.getJSON in JQuery

I get the German text of a specific keyword (

var title
) and output it as html afterwards. This is working fine, but now I wanted to load the English text if the German text isn't available. This is also working fine with my code:

var length = 500;
var title = $('#title').attr('data-title');
var lang = 'de';
var url = 'https://' + lang + '.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';

$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
var text = val['extract'];
console.log('lang-' + lang + '-text: ' + text);
if (text) {
text = text.replace('Siehe auch:', '');
} else if (!text && lang != 'en') {
var url = 'https://en.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
text = val['extract'];
console.log('lang-en-text: ' + text);
});
});
}
console.log('lang-end-text: ' + text);

if (text) {
text = text.length > length ? text.substring(0, length - 3) + '...' : text;
$('#text').html(text);
} else {
setTimeout(function () {
$('#text').html('<?= __('EMPTY'); ?>');
}, 1000);
}

console.log(data);
});
});


But after the second $.getJSON is closed,
text
is empty again. That means that


console.log('lang-en-text: ' + text);


is working and outputs the correct English text in the console, but after closing the $.getJSON the variable
text
has no value anymore, what I can confirm with the output in the console:


console.log('lang-end-text: ' + text);


How can I keep the value? Also is there a better way to check if the specific content I want to get (the text in this case) is available BEFORE, so I don't have to make two
$.getJSON
requests? Or is my way the right way to do it?

EDIT: It's working now!

I found the solution thanks to
moopet
and used
.done
and a new function called
.setText
to set the text. Maybe this helps others too as the question seems to get upvoted a lot. This is my code now:

var length = 500;
var title = $('#title').attr('data-title');
var lang = 'de';
var url = 'https://' + lang + '.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';

$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
var text = val['extract'];
console.log('lang-' + lang + '-text: ' + text);
if (text) {
text = text.replace('Siehe auch:', '');
} else if (!text && lang != 'en') {
var url = 'https://en.wikipedia.org/w/api.php?format=json&action=query' +
'&prop=extracts&exintro=&explaintext=&titles=' + title + '&redirects=0';
$.getJSON("http://query.yahooapis.com/v1/public/yql",
{
q: "select * from json where url=\"" + url + "\"",
format: "json"
},
function (data) {
$.each(data.query.results.json.query.pages, function (key, val) {
text = val['extract'];
console.log('lang-en-text: ' + text);
});
}).done(function() {
setText(text);
});
}
console.log(data);
});
}).done(function() {
setText(text);
});

function setText(text) {
if (text) {
text = text.length > length ? text.substring(0, length - 3) + '...' : text;
$('#text').html(text);
} else {
$('#text').html('Text not available.');
}
}

Answer

You're running afoul of asynchronous javascript calls.

Your success callback:

function (data) {
    $.each(data.query.results.json.query.pages, function (key, val) {
        text = val['extract'];
        console.log('lang-en-text: ' + text);
    });
});

is called asynchronously. In other words, it's deferred until the HTTP request has finished.

Your

console.log('lang-end-text: ' + text);

is called immediately, before text is assigned, because that's how execution progresses. If you put the code for things you want to do with the text inside the callback function, you'll get the results you want.

Comments