Возврат Javascript, не прерывающий работу
У меня есть функция javascript, которая проверяет, существует ли художник в файле XML:
function artistExists(artist) {
// get data from artists.xml
$('.loading').show();
$.get(artists_xml, function(xml){
$('.loading').hide();
$(xml).find('artist').each(function(){
if ($(this).find("ar_artist").text() == artist.val()) {
alert ('artist exists');
return true;
} //end if
}); // end each
alert ('artist does not exist');
return false;
}); // end .get function
} // end of artistExists function
Я правильно понял, что строка "return true" должна прекратить выполнение функции? Я думал, что это произойдет, но после обнаружения записи и запуска первого запуска предупреждения продолжается предупреждение о сбое внизу.
Что я делаю неправильно? Спасибо.
Ответы
Ответ 1
Верните false
, а не true
, чтобы закончить цикл each
; от документы:
Мы можем остановить цикл из функции обратного вызова, возвращая false
.
Это приведет к завершению вашего цикла each
, но не общей функции. Вам нужно установить флаг, чтобы вы знали, что вы нашли что-то, например. что-то вроде этого:
function artistExists(artist) {
// get data from artists.xml
$('.loading').show();
$.get(artists_xml, function(xml){
var found = false; // <== Added
$('.loading').hide();
$(xml).find('artist').each(function(){
if ($(this).find("ar_artist").text() == artist.val()) {
alert ('artist exists');
found = true; // <== Added
return false; // <== Modified
} //end if
}); // end each
if (!found) { // <== Added
alert ('artist does not exist');
} // <== Added
return found; // <== Modified
}); // end .get function
} // end of artistExists function
Ответ 2
Да, это "завершает" выполнение функции. Вопрос в том, "какая функция?" В этом случае ответ должен быть довольно ясным: он передал функцию .each()
.
Вы можете завершить поведение цикла .each()
, вернув false
вместо true
, но это все равно не приведет вас к нарушению функции. То, что вы, вероятно, должны учитывать, - это установить локальную переменную во внешней функции и установить внутреннюю функцию, когда она что-то находит (а затем разбивает цикл .each()
). Затем основная функция может проверить локальную переменную, чтобы увидеть, была ли она установлена.
Это случай, когда я действительно хотел бы использовать API .reduce()
или .inject()
, но у jQuery его нет, и они действительно противятся ему.
Ответ 3
$.get
является асинхронной функцией, то есть основная функция artistExists
будет немедленно возвращаться, и будет инициирован запрос GET. Чтобы получить результат, вам потребуется обратный вызов.
function artistExists(artist, cb) {
$('.loading').show();
$.get(artists_xml, function(xml) {
var found = false;
$('.loading').hide();
$(xml).find('artist').each(function(){
if ($(this).find("ar_artist").text() == artist.val()) {
found = true;
return false; // use return false to stop .each()
}
});
// the built in action.
if (found) {
alert ('artist exists');
} else {
alert ('artist does not exist');
}
// call the callback function
cb (found);
});
}
Затем для использования вам необходимо использовать функцию обратного вызова. От
var isExists = artistExists('lol');
// do stuff
Вам нужно изменить его на:
artistExists('lol', function(isExists) {
// do stuff
});
Ответ 4
Спасибо за все советы. В конце концов я решил, что мне нужен синхронный вызов, поэтому я сделал следующую новую версию функции .get, называемую .sget:
jQuery.extend({
sget: function( url, callback, type ) {
return jQuery.ajax({
type: "GET",
url: url,
success: callback,
async: false,
dataType: type
});
}
});
Пара "async: false" в параметрах "ajax" делает синхронный вызов. Затем следующее редактирование моей исходной функции:
function artistExists(artistname) {
var found = false;
console.log("From Input:Artist= " + artistname.val());
// get data from artists.xml
$('.loading').show();
$.sget(artists_xml, function(xml){ // new synchronous get
$('.loading').hide();
$(xml).find('artist').each(function(){
if ($(this).find("ar_artist").text() == artistname.val()) {
console.log('From File:Artist= ' + $(this).find("ar_artist").text());
found = true;
console.log("In each loop:Flag= " + found);
return;
} //end if
}); // end each
}); // end .get function
console.log("At end:Flag= " + found);
return found;
}
Строки console.log будут удалены. Они показывают, что сейчас все происходит в том порядке, в котором я хочу. Итак, новая синхронная функция .sget и использование флага "найден", как было сказано выше, сделали трюк для меня. Не знаю, почему я не мог думать об этом вчера.
Спасибо всем.