我有一个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'行应该退出函数的执行?我以为会这样,但是在找到记录并运行第一个警报后,执行继续到底部的故障警报。
我做错了什么?谢谢。
答案 0 :(得分:15)
是的,它确实“退出”了该功能的执行。问题是,“哪个功能?”在这种情况下,答案应该非常明确:它是传递给.each()
的函数。
您可以通过返回.each()
而不是false
来终止true
的循环行为,但这仍然不会让您退出外部函数。您应该考虑的是在外部函数中设置局部变量,并在找到内容时设置内部函数(然后打破.each()
循环)。然后main函数可以检查局部变量以查看它是否已设置。
在这种情况下,我真的想使用.reduce()
或.inject()
API,但jQuery没有,并且他们真的反对它。
答案 1 :(得分:14)
返回false
而不是true
来终止each
循环;来自the docs:
我们可以通过返回
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 :(得分:4)
$.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
});
答案 3 :(得分:1)
感谢您的所有建议。最后我决定需要一个同步调用,所以我创建了以下新版本的.get函数,名为.sget:
jQuery.extend({
sget: function( url, callback, type ) {
return jQuery.ajax({
type: "GET",
url: url,
success: callback,
async: false,
dataType: type
});
}
});
'ajax'选项中的'async:false'对使调用同步。然后编辑我原来的失败函数:
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函数和使用'found'标志,如上所述,已经为我做了诀窍。不知道为什么我昨天想不到这样做。
谢谢大家。