2011-01-23 28 views
12

Tôi có một hàm javascript mà sẽ kiểm tra xem nếu một nghệ sĩ tồn tại trong một tập tin XML:Javascript trả lại không phá vỡ ra khỏi chức năng

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 

Tôi có ngay trong suy nghĩ rằng 'trả về true' dòng nên bỏ thi của hàm? Tôi nghĩ rằng nó sẽ, nhưng sau khi tìm thấy một kỷ lục và chạy thực hiện cảnh báo đầu tiên tiếp tục thông báo thất bại ở phía dưới.

Tôi làm gì sai? Cảm ơn bạn.

Trả lời

14

Trả lại false, thay vì true, để chấm dứt vòng each; từ the docs:

Chúng tôi có thể ngừng vòng lặp trong chức năng gọi lại bằng cách trả lại false.

Điều đó sẽ chỉ chấm dứt vòng lặp each của bạn, tuy nhiên, không phải là chức năng tổng thể. Bạn sẽ cần đặt cờ để bạn biết mình có tìm thấy gì không, ví dụ: một cái gì đó như thế này:

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 
+0

Đã lâu rồi, nhưng tôi có một câu hỏi về nó: Tôi đã cố gắng sử dụng 'return' chỉ và nó dừng' .each', vậy là 'return false' không phải là phải làm hoặc có cái gì đó Tôi nên biết? –

+1

@CagatayUlubay: Chỉ 'return' sẽ không dừng vòng lặp' each', nó chỉ nhảy ra khỏi cuộc gọi lại cho lần lặp lại đó; vòng lặp sẽ tiếp tục với lần lặp tiếp theo. 'return false' sẽ nhảy ra khỏi hàm gọi lại cho vòng lặp lặp lại đó ** và **. –

14

Có, thực hiện "thoát" chức năng. Câu hỏi đặt ra là "chức năng nào?" Trong trường hợp này câu trả lời phải khá rõ ràng: đó là hàm được chuyển đến .each().

Bạn có thể chấm dứt hoạt động lặp của .each() bằng cách trả lại false thay vì true, nhưng điều đó vẫn không giúp bạn thoát khỏi chức năng bên ngoài. Những gì bạn có lẽ nên xem xét là để thiết lập một biến địa phương trong các chức năng bên ngoài, và có chức năng bên trong thiết lập rằng khi nó tìm thấy một cái gì đó (và sau đó phá vỡ các vòng lặp .each()). Sau đó, chức năng chính có thể kiểm tra biến cục bộ để xem nó có được đặt hay không.

Đây là trường hợp tôi thực sự muốn sử dụng API .reduce() hoặc .inject(), nhưng jQuery không có và họ thực sự phản đối.

+0

Cảm ơn Pointy, nó hoạt động, mặc dù nó có vẻ hơi clunky phải không. Nó sẽ là tuyệt vời nếu có thể đặt số sau một tuyên bố phá vỡ. – RichJohnstone

+0

Vấn đề là khi các hàm của bạn là các giá trị hạng nhất như trong JavaScript, sự sắp xếp "tĩnh" của mã thực sự không cho bạn biết nhiều về cách thức/khi nào/nơi một hàm thực sự được gọi. – Pointy

4

$.get là chức năng không đồng bộ, có nghĩa là chức năng chính, artistExists sẽ trả về ngay lập tức và yêu cầu GET sẽ được bắt đầu. Để có thể nhận được kết quả, bạn sẽ cần một cuộc gọi lại.

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); 

    }); 
} 

Sau đó, để sử dụng, bạn cần phải sử dụng chức năng gọi lại. Từ

var isExists = artistExists('lol'); 
// do stuff 

Bạn cần phải thay đổi nó thành:

artistExists('lol', function(isExists) { 
    // do stuff 
}); 
+0

Cảm ơn Thái Lan - về sự cải tiến này rõ ràng là con đường để đi. Tôi chỉ không hoàn toàn hiểu cách sử dụng nó trong mã của tôi, tôi mới và tôi chưa bao giờ sử dụng một cuộc gọi lại trước đây. Tôi muốn có một dòng mã như "if (artistExists ($ ('# artistfield'))) {// do stuff}". Làm thế nào tôi sẽ đi về điều này với các doanh nghiệp gọi lại xin vui lòng? Cảm ơn rất nhiều. – RichJohnstone

+0

Một chức năng không đồng bộ có nghĩa là một chức năng mà bạn không thể nhận được kết quả ngay lập tức khi bạn gọi. Chức năng gọi lại rất quan trọng để bạn có thể được thông báo khi có kết quả. Nếu bạn xem xét, hàm 'artistExists' chấp nhận một đối số' cb', và 'cb' được gọi sau khi chúng ta có kết quả trên' cb (found) '. – Thai

+0

cảm ơn Thái Lan lần nữa. Tôi hiểu rằng bản chất không đồng bộ của yêu cầu có nghĩa là tôi phải đợi kết quả. Những gì tôi không rõ ràng về là làm thế nào tôi sử dụng chức năng cb/callback của tôi để vượt qua true/false trở lại dòng lệnh gọi ban đầu của tôi. Nếu bạn có thể giúp tôi với một chút mã ở đây tôi thực sự biết ơn. cảm ơn một lần nữa. – RichJohnstone

1

Cảm ơn tất cả những lời khuyên. Cuối cùng tôi quyết định tôi cần một cuộc gọi đồng bộ, vì vậy tôi đưa ra phiên bản mới như sau của hàm .get, gọi .sget:

jQuery.extend({ 
sget: function(url, callback, type) { 
     return jQuery.ajax({ 
      type:  "GET", 
      url:  url, 
      success: callback, 
      async:  false, 
      dataType: type 
     }); 
    } 
}); 

Các 'async: false' cặp trong các tùy chọn của ajax 'làm cho gọi đồng bộ.Sau đó chỉnh sửa sau chức năng thất bại ban đầu của tôi:

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; 

}

Các dòng console.log sẽ bị xóa. Họ cho thấy mặc dù, rằng mọi thứ đang xảy ra theo thứ tự tôi muốn. SO chức năng đồng bộ .sget mới và sử dụng cờ 'tìm thấy', như đã đề cập ở trên, đã thực hiện thủ thuật cho tôi. Không biết tại sao tôi không thể nghĩ đến việc này vào ngày hôm qua.

Cảm ơn mọi người.

Các vấn đề liên quan