//- 체크 박스 전부 선택

$('.total_check').click(function(e){

// Iterate each checkbox

if(this.checked){

$(':checkbox').each(function() {

this.checked = true;

});

}else{

$(':checkbox').each(function() {

this.checked = false;

})

}

});

블로그 이미지

칩사마코더

,

Node.js의 비동기 반복 패턴 - 2 부

이것은 이전 기사 "비동기 반복 패턴"의 후속 조치입니다.

최신 피드백은 훌륭했으며 일부 수정 및 의견은 저에게 전달되었습니다.

또한, 일부 node.js 증오는 비동기 IO를 처리하는 데 필요한 몇 번 추가 된 복잡성으로 인해 확산되었습니다. 비동기 IO를 처리하는 것에 대한 두려움을 퍼트 리고이를 처리하는 방법에 대한 나의 견해를 모으고 전파하려는 의도는 아닙니다. 제 견해로는, 무위험 주의자는 좋으며 여기에 머물러 있으려면 그것을 포용하는 법을 배워야합니다.

그러나 첫째, 수정 :

Doh!

일부 독자들은 비동기 IO 작업을 호출하여 스택에서 이미 분리 중이므로 serialize_timeout.js 버전 (setTimeout을 사용하여 스택에서 분리하는 부분)이 필요하지 않다는 경고를 받았습니다.

너 맞아.

사과와 오렌지 - 공정한

node.js IO 프로그래밍과 "정상적인"블로킹 프로그래밍을 비교하려고한다면, 공정하고 합당한 두 객체를 비교해 보겠습니다.

필자의 견해로, IO API를 차단하지 않는 IO API와 구문을 비교하는 것은 공정하지 못합니다. 차단을 사용하면 훨씬 많은 작업을 수행 할 수 있기 때문입니다. 두 가지를 모두 비교하려면 node.js 솔루션과 차단 세계의 다음 솔루션을 비교해야합니다.

비 차단 입출력은 백그라운드에서 많은 입출력 작업을 수행 할 수 있기 때문에 차단 세계에서 동일한 기능을 비교하는 것이 타당합니다.

블로킹 세계에서 똑같은 동작을하기 위해서는 먼저 스레드 풀을 가지고 있어야합니다. 아니요, 각 IO 작업에 대해 새 스레드를 새로 만들지 않아도됩니다. node.js가 해당 오버 헤드를 없애기 때문입니다.

그런 다음 각 IO 작업을 스레드 풀의 새 스레드에 할당해야합니다.

그런 다음 주 스레드는 그 중 하나에서 완료 신호를 기다리는 것을 차단합니다.

각 스레드는 모든 작업이 언제 완료되는지를 알기 위해 전역 완료 카운터를 유지해야합니다. 그리고 예, 스레드 액세스를 해당 메모리에 동기화해야합니다.

한 스레드가 모든 작업이 완료되었음을 감지하면 차단 해제를 위해 대기중인 주 스레드에 알립니다. 제 의견으로는 간단하지 않습니다.

공동 루틴, 연속체, 파이버로 협업 멀티 태스킹을 호출 할 수도 있습니다. 단순화 될 것입니다. 카운터에 대한 액세스를 동기화 할 필요는 없지만 여러 컨텍스트를 관리해야합니다. 또한, 내 생각에 단순하지.

추상화

또한이 기사는 기본 패턴과 그 결과를 폭로하는 데 도움이되었습니다. 일상적인 프로그래머는 이러한 복잡성을 처리 할 필요가 없습니다. 그래서 일부 추상화가 고안되었습니다.

다음은 그 중 하나입니다.

단계

단계는 Tim Caswell의 흐름 제어 라이브러리입니다. 그것은 쉬운 방법으로 체이닝 콜백을 허용합니다.

예를 들어 async라고하는 함수가 있다고 가정 해 봅시다. 비동기 IO를 시뮬레이션하여 데이터베이스 상호 작용에서 벗어나게합니다.

function async(i, callback) {
  timeout = Math.round(Math.random() * 3000);
  setTimeout(function() {
    console.log(i + ' is done');
    callback();
  }, timeout);
}

다음으로 npm을 사용하여 단계를 설치해야합니다.

$ npm install step

그런 다음 데이터베이스에 10 개의 요소를 병렬로 삽입해야합니다.

var Step = require('step');

var collection = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

Step(

  function insertAll() {
    var self = this;
    collection.forEach(function(element) {
      async(element, self.parallel());
    });
  },
  function finalize(err) {
    if (err) { console.log(err);return;}
    console.log('done with no problem');
  }
);

당신은 단순히 2 개의 기능을 가진 step을 사용할 것입니다.

처음에는 모든 요소를 ​​병렬로 삽입합니다. 콜백에 this.parallel ()을 전달하면 병렬 요청을 처리하는 콜백을 생성하는 방법입니다.

블로그 이미지

칩사마코더

,

Node.js의 비동기 반복 패턴

node.js에서 IO를 수행 할 때처럼 비동기 적으로 프로그래밍 할 때 특히 이해하기 어려운 패턴이 있습니다.

예를 들어 다음 루틴을 프로그래밍해야한다고 가정 해 보겠습니다.

데이터베이스에 개체 컬렉션을 삽입 한 다음 완료되면 콜백을 호출합니다. 그래서 이것을 동기식으로 작성해야한다면 다음과 같이 할 수 있습니다 :

function insertCollection(collection) {
  for(var i = 0; i < collection.length; i++) {
    db.insert(collection[i]);
  }
}

따라서 node.js를 사용하기 때문에 db.insert가 비동기 일 가능성이 높습니다. 이것을 비동기 함수로 바꾸어야합니다.

나는이 같은 명백하게 잘못된 implents를 보았다 :

function insertCollection(collection, callback) {
  for(var i = 0; i < collection.length; i++) {
    db.insert(collection[i], function(err) {
      if (err) {
        throw err;
      }
    });
  }
  callback();
}

이 문제는 명백합니다. 콜백은 백그라운드에서 모든 db.inserts를 시작한 직후에 호출되며 완료 할 기회를 남기지 않습니다. 콜백이 호출되면 삽입이 종료되지 않습니다.

또 다른 접근법은 다음과 같습니다.

function insertCollection(collection, callback) {
  for(var i = 0; i < collection.length; i++) {
    (function(i) {
      db.insert(collection[i], function(err) {
        if (err) {
          callback(err);
          return;
        }
        if (i == (collection.length - 1)) {
          callback();
        }
      });
    })(i);
  }
}

따라서 "마지막 삽입물이 콜백 할 때 전화해야합니다"라고 생각할 유혹이 있습니다. 그러나 이것은 틀린 것입니다. 마지막 한 콜백이 실행될 때 첫 번째 삽입이 여전히 실행 중일 수 있습니다. 너는 결코 알지 못한다.

가장 안전한 방법은 다음과 같이하는 것입니다.

function insertCollection(collection, callback) {
  var inserted = 0;
  for(var i = 0; i < collection.length; i++) {
    db.insert(collection[i], function(err) {
      if (err) {
        callback(err);
        return;
      }
      if (++inserted == collection.length) {
        callback();
      }
    });
  }
}

모든 삽입이 콜백되었을 때만 콜백해야합니다.

직렬화

때로는 흐름 및 / 또는 실행 순서를 제어하려고합니다.

이 경우 삽입물을 완벽하게 정렬하거나 오류가 발생하면 삽입을 중단하여보다 쉽게 ​​복구 할 수 있습니다.

이 경우 다음과 같이 할 수 있습니다.

function insertCollection(collection, callback) {
  var coll = collection.slice(0); // clone collection
  (function insertOne() {
    var record = coll.splice(0, 1)[0]; // get the first record of coll and reduce coll by one
    db.insert(record, function(err) {
      if (err) { callback(err); return }
      if (coll.length == 0) {
        callback();
      } else {
        insertOne();
      }
    }
  })();
}

여기에서는 꼬리 재귀를 사용하여 레코드를 계속 삽입합니다.

이 예제에는 한 가지 문제가 있습니다. 스택을 사용하므로 컬렉션이 너무 크면 스택이 끊어 질 수 있습니다.

이 문제에 대한 한 가지 해결책은 재귀 할 때 스택을 포기하는 것입니다. 그리고 당신은 0의 timeout 값을 가진 setTimeout을 사용하여 그것을 할 수 있습니다. 스택이 unwind 된 후에 inner 함수가 호출되도록합니다 :

function insertCollection(collection, callback) {
  var coll = collection.slice(0); // clone collection
  (function insertOne() {
    var record = coll.splice(0, 1)[0]; // get the first record of coll and reduce coll by one
    db.insert(record, function(err) {
      if (err) { callback(err); return }
      if (coll.length == 0) {
        callback();
      } else {
        setTimeout(insertOne, 0);
      }
    }
  })();
}

후속 조치

후속 기사 Node.js의 비동기 반복 패턴보기 - 2 부

최신 정보:

또한 (Tim Caswell이 지적한 바와 같이) 콜백으로 끝나는 대신 이벤트 루프로 예외가 되돌아 가지 않는 것이 중요합니다. 따라서 db.insert 또는 다른 외부 함수 호출을 래핑해야합니다. 마지막 예는 다음과 같습니다.

function insertCollection(collection, callback) {
  var coll = collection.slice(0); // clone collection
  (function insertOne() {
    var record = coll.splice(0, 1)[0]; // get the first record of coll and reduce coll by one
    try {
      db.insert(record, function(err) {
        if (err) { callback(err); return }
        if (coll.length == 0) {
          callback();
        } else {
          insertOne();
        }
      }
    } catch (exception) {
      callback(exception);
    }
  })();
}


블로그 이미지

칩사마코더

,