Tiếp tục trực tiếp trên con trỏ trong con trỏ.forEach ()


278

Tôi đang xây dựng một ứng dụng bằng cách sử dụng metseng.js và MongoDB và tôi có một câu hỏi về con trỏ.forEach (). Tôi muốn kiểm tra một số điều kiện ở đầu mỗi lần lặp forEach và sau đó bỏ qua phần tử nếu tôi không phải thực hiện thao tác trên nó để tôi có thể tiết kiệm thời gian.

Đây là mã của tôi:

// Fetch all objects in SomeElements collection
var elementsCollection = SomeElements.find();
elementsCollection.forEach(function(element){
  if (element.shouldBeProcessed == false){
    // Here I would like to continue to the next element if this one 
    // doesn't have to be processed
  }else{
    // This part should be avoided if not neccessary
    doSomeLengthyOperation();
  }
});

Tôi biết tôi có thể biến con trỏ thành mảng bằng cách sử dụng con trỏ.find (). Fetch () và sau đó sử dụng vòng lặp for thường xuyên để lặp lại các phần tử và sử dụng tiếp tục và phá vỡ bình thường nhưng tôi quan tâm nếu có một cái gì đó tương tự để sử dụng trong forEach ( ).

Câu trả lời:


560

Mỗi lần lặp lại forEach()sẽ gọi hàm mà bạn đã cung cấp. Để dừng xử lý thêm trong bất kỳ lần lặp cụ thể nào (và tiếp tục với mục tiếp theo), bạn chỉ cần returntừ hàm tại điểm thích hợp:

elementsCollection.forEach(function(element){
  if (!element.shouldBeProcessed)
    return; // stop processing this iteration

  // This part will be avoided if not neccessary
  doSomeLengthyOperation();
});

18
Bạn có biết những gì có thể là "phá vỡ" sau đó nếu tiếp tục chỉ là "trở lại;".
Drag0

5
Tôi không sử dụng MongoDB vì vậy chưa đọc tài liệu của nó, nhưng có thể nó return false;tương đương với break;(vì nó là một .each()vòng lặp jQuery ). Tất nhiên, bất cứ ai thực hiện MongoDB đều .forEach()có thể có những ý tưởng khác ...
nnnnnn

9
@ Drag0 Bạn có thể sử dụng .some () để thay thế cho .forEach (), cho phép bạn trả về false để phá vỡ vòng lặp.
Andrew

6
@Andrew Bạn có thể sử dụng some, chỉ cần lưu ý rằng bạn đang sử dụng sai (hoặc sử dụng một cách sáng tạo) một chức năng được dự định để biết nếu có bất kỳ yếu tố nào phù hợp với điều kiện. Kiểu như khi tôi thấy mọi người sử dụng mapvà bỏ qua kết quả (đáng lẽ họ nên sử dụng forEach). Đó là ngữ nghĩa, mọi người sẽ phải nhìn hai lần để biết tại sao bạn lại sử dụng somekhi bạn không thực sự quan tâm đến kết quả
Juan Mendes

1
@Andrew mẹo tuyệt vời, tuy nhiên, nó return truesẽ phá vỡ một số vòng lặp
daviestar

11

Theo tôi, cách tiếp cận tốt nhất để đạt được điều này bằng cách sử dụng filter phương pháp vì việc quay trở lại trong một forEachkhối là vô nghĩa ; cho một ví dụ trên đoạn trích của bạn:

// Fetch all objects in SomeElements collection
var elementsCollection = SomeElements.find();
elementsCollection
.filter(function(element) {
  return element.shouldBeProcessed;
})
.forEach(function(element){
  doSomeLengthyOperation();
});

Điều này sẽ thu hẹp của bạn elementsCollectionvà chỉ giữ các filtredyếu tố cần được xử lý.


3
Điều này sẽ lặp lại các yếu tố được tìm thấy hai lần, một lần trong filterlần thứ hai và lần thứ hai forEachnếu nó là một bộ sưu tập lớn, nó sẽ rất không hiệu quả
Dementic

1
Bạn nói đúng, nhưng tôi không nghĩ đó là vấn đề lớn vì sự phức tạp về thời gian của điều này sẽ O(2n)có thể được coi là O(n).
Ramy Tamer

2
Xem xét SO đang được sử dụng bởi những người khác, không chỉ OP, đăng một giải pháp chỉ nhằm mục đích đăng nó, đang tạo ra nhiều tác hại hơn là tốt. Câu trả lời ở trên thực hiện nó trong một lần lặp và là rightcách để làm điều đó.
Mất trí nhớ

Lưu ý rằng bộ sưu tập của OP không phải là một mảng, đó là một đối tượng con trỏ Mongo DB, dường như không có .filter()phương thức, vì vậy bạn phải gọi .toArray()phương thức của nó trước khi bạn có thể.filter()
nnnnnn

7

Đây là một giải pháp sử dụng for ofcontinuethay vì forEach:


let elementsCollection = SomeElements.find();

for (let el of elementsCollection) {

    // continue will exit out of the current 
    // iteration and continue on to the next
    if (!el.shouldBeProcessed){
        continue;
    }

    doSomeLengthyOperation();

});

Điều này có thể hữu ích hơn một chút nếu bạn cần sử dụng các hàm không đồng bộ bên trong vòng lặp không hoạt động bên trong forEach. Ví dụ:


(async fuction(){

for (let el of elementsCollection) {

    if (!el.shouldBeProcessed){
        continue;
    }

    let res;

    try {
        res = await doSomeLengthyAsyncOperation();
    } catch (err) {
        return Promise.reject(err)
    }

});

})()

2

Sử dụng đánh giá ngắn mạch JavaScripts . Nếu el.shouldBeProcessedtrả về đúng,doSomeLengthyOperation

elementsCollection.forEach( el => 
  el.shouldBeProcessed && doSomeLengthyOperation()
);
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.