Подтвердить что ты не робот

Возврат 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" должна прекратить выполнение функции? Я думал, что это произойдет, но после обнаружения записи и запуска первого запуска предупреждения продолжается предупреждение о сбое внизу.

Что я делаю неправильно? Спасибо.

4b9b3361

Ответ 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 и использование флага "найден", как было сказано выше, сделали трюк для меня. Не знаю, почему я не мог думать об этом вчера.

Спасибо всем.