node 의 async 프로 세 스 제어 패키지 parallel 의 실현

Async 소개
 
Async 는 프로 세 스 제어 도구 패키지 로 직접적 이 고 강력 한 비동기 기능 을 제공 합 니 다.자바 script 을 기반 으로 Node. js 로 디자인 되 었 으 며 브 라 우 저 에서 도 직접 사용 할 수 있 습 니 다.
 
Async 는 약 20 개의 함 수 를 제공 합 니 다. 자주 사용 하 는 map, reduce, filter, foreach 등 을 포함 하고 비동기 프로 세 스 제어 모델 은 직렬 (series), 병렬 (parallel), 폭포 (waterfall) 등 을 포함 합 니 다.
 
항목 주소:https://github.com/caolan/async
 
Async 함수 소개
 
async 기반 0.2.9 버 전.
 
async 는 주로 세 부분의 절차 제어 기능 을 실현 했다.
 
집합: Collections
흐름 제어: 제어 흐름
도구 종류: Utils
1). 집합: Collections
 
each: 같은 집합 에 있 는 모든 요소 에 대해 같은 비동기 작업 을 수행 하려 면.
map: 집합 에 있 는 모든 요소 에 대해 비동기 작업 을 수행 하여 결 과 를 얻 습 니 다.모든 결 과 는 최종 콜백 에 합 쳐 집 니 다.each 와 의 차이 점 은 each 는 마지막 값 에 만 관심 을 가지 고 map 가 관심 을 가 지 는 마지막 값 입 니 다.
filter: 집합 에 있 는 요 소 를 비동기 로 선별 합 니 다. 주의해 야 할 것 은 iterator 의 callback 은 하나의 인자 만 있 고 true 나 false 만 받 을 수 있 습 니 다.
reject: reject 는 filter 와 정반 대 입 니 다. true 로 테스트 할 때 버 립 니 다.
reduce: 집합 에 있 는 모든 요소 와 연산 하여 마지막 으로 값 을 얻 을 수 있 는 초기 값 을 지정 할 수 있 습 니 다.reduce 는 왼쪽 에서 오른쪽으로 요 소 를 옮 겨 다 니 며 오른쪽 에서 왼쪽으로 가 려 면 reduceRight 를 사용 할 수 있 습 니 다.
detect: 집합 에서 조건 을 만족 시 키 는 첫 번 째 요 소 를 얻 는 데 사용 합 니 다.
sortby: 집합 안의 요 소 를 정렬 하고 모든 요소 에 따라 특정한 비동기 작업 을 한 후에 발생 하 는 값 을 작은 것 에서 큰 것 으로 정렬 합 니 다.
some: 집합 에 최소한 하나의 요소 가 조건 을 만족 시 킬 수 있 는 지 여부 가 있 을 때, 최종 callback 에서 얻 은 값 은 true 이 고, 그렇지 않 으 면 false 입 니 다.
every: 집합 에 있 는 모든 요소 가 조건 을 만족 시 키 면 최종 반전 의 result 에 true 로 전 달 됩 니 다. 그렇지 않 으 면 false 입 니 다.
concat: 여러 비동기 작업 의 결 과 를 하나의 배열 로 합 칩 니 다.
2). 프로 세 스 제어: 제어 흐름
 
series: 직렬 실행, 한 함수 배열 의 모든 함수, 모든 함수 가 실 행 된 후에 야 다음 함 수 를 실행 할 수 있 습 니 다.
parallel: 여러 함 수 를 병행 하여 실행 합 니 다. 모든 함 수 는 즉시 실 행 됩 니 다. 다른 함수 가 먼저 실 행 될 때 까지 기다 릴 필요 가 없습니다.최종 콜백 에 전 달 된 배열 의 데 이 터 는 완 료 된 순서 가 아 닌 tasks 에서 설명 한 순서 입 니 다.
whilst: while 에 해당 하지만, 그 중의 비동기 호출 은 완 료 된 후에 야 다음 순환 을 진행 할 수 있 습 니 다.
doWhilst: do.. while 에 해당 하 는 doWhilst 는 fn, test 의 매개 변수 위 치 를 교환 하고 순환 을 한 번 실행 한 다음 에 test 판단 을 합 니 다.
until: until 은 whilst 와 정반 대 입 니 다. test 가 false 일 때 순환 하고 true 일 때 튀 어 나 옵 니 다.기타 특성 일치.
doUntil: doUntil 은 doWhilst 와 정반 대 입 니 다. test 가 false 일 때 순환 하고 true 일 때 튀 어 나 옵 니 다.기타 특성 일치.
forever: 조건 이 순환 되 든 틀 리 지 않 으 면 콜 백 은 영원히 실행 되 지 않 습 니 다.
waterfall: 순서대로 함수 한 세트 를 실행 합 니 다.모든 함수 에서 발생 하 는 값 은 다음 에 전 달 됩 니 다.
compose: 비동기 함 수 를 포함 하 는 함수 집합 을 만 듭 니 다. 함수 마다 지난번 함수 의 반환 값 을 소비 합 니 다.f (), g (), h () 비동기 함 수 를 f (g (h ()) 로 조합 하여 콜백 을 통 해 값 을 되 돌려 줍 니 다.
apply Each: 한 배열 의 모든 함수 에 같은 인 자 를 전달 하고 callback 을 통 해 되 돌려 줍 니 다.첫 번 째 인자 만 전달 하면 함수 대상 을 되 돌려 줍 니 다. 호출 할 수 있 습 니 다.
quue: 직렬 메시지 큐 입 니 다. 워 커 수 를 제한 하여 한꺼번에 실행 하지 않 습 니 다.워 커 의 수가 부족 할 때, 새로 추 가 된 작업 은 새로운 워 커 가 사용 할 수 있 을 때 까지 줄 을 서서 기다 릴 것 입 니 다.
cargo: queue 와 같은 직렬 메시지 큐 입 니 다. 워 커 수 를 제한 하여 한꺼번에 실행 하지 않 습 니 다.다른 점 은 cargo 가 매번 만원 의 작업 을 작업 단위 로 불 러 오고 작업 단위 에서 모두 수행 한 후에 만 새로운 작업 단 위 를 불 러 옵 니 다.
auto: 의존 관계 가 있 는 여러 작업 의 수행 을 처리 합 니 다.
iterator: 한 그룹의 함 수 를 하나의 iterator 로 포장 합 니 다. 이 iterator 를 처음 호출 할 때 정 의 된 첫 번 째 함 수 를 실행 하고 두 번 째 함 수 를 되 돌려 줍 니 다.
apply: 함수 에 여러 개의 인 자 를 미리 연결 하고 직접 호출 할 수 있 는 새로운 함 수 를 생 성하 여 코드 를 간소화 할 수 있 습 니 다.
nextTick: nodejs 의 nextTick 과 같이 마지막 으로 함 수 를 호출 합 니 다.
times: 비동기 실행, times 는 몇 번 호출 할 지 지정 하고 결 과 를 배열 에 합 쳐 되 돌려 줍 니 다.
timesSeries: time 과 유사 하 며, 유일 하 게 다른 것 은 동기 화 실행 입 니 다.
3). 도구 종류: Utils
 
memoize: 어떤 함수 가 메모리 에 계산 결 과 를 캐 시 하도록 합 니 다.같은 매개 변수 에 대해 서 는 한 번 만 계산 하고 다음 에는 그 전에 계산 한 결 과 를 바로 얻 을 수 있 습 니 다.
unmemoize: 캐 시 된 함 수 를 캐 시 되 지 않 은 함수 로 되 돌려 줍 니 다.
log: 비동기 함 수 를 실행 하고 반환 값, 로그 출력 을 기록 합 니 다.
dir: log 와 유사 합 니 다. 다른 점 은 브 라 우 저의 console. dir () 함 수 를 호출 하여 DOM 보기 로 표시 합 니 다.
noConflict: 이전에 전역 에서 async 변 수 를 정의 했다 면, 이 async. js 를 가 져 올 때, 이전의 async 변 수 를 저장 한 다음 덮어 씁 니 다.브 라 우 저 에 만 사용 되 며, nodejs 에 서 는 사용 되 지 않 습 니 다. 보 여 드릴 수 없습니다.
4. async_데모 사용 안내
 
자세 한 사용 은 github 소스 코드 를 참고 하 십시오:https://github.com/bsspirit/async_demo
 
각 함수 의 용법 은 매우 상세 한 실례 가 있다!!
 
5. 장면: 데이터베이스 에 대한 연속 조작
 
이 장면 의 배경 상황 은 Nodejs 로 MySQL 을 연결 하 는 것 을 참고 하 십시오.
 
원래 장면 에서 데이터 직렬 조작, 추가 삭제 검사 (CRUD), 코드 는 다음 과 같 습 니 다.
var mysql = require('mysql');
var conn = mysql.createConnection({
    host: 'localhost',
    user: 'nodejs',
    password: 'nodejs',
    database: 'nodejs',
    port: 3306
});
conn.connect();

var insertSQL = 'insert into t_user(name) values("conan"),("fens.me")';
var selectSQL = 'select * from t_user limit 10';
var deleteSQL = 'delete from t_user';
var updateSQL = 'update t_user set name="conan update"  where name="conan"';

//delete
conn.query(deleteSQL, function (err0, res0) {
    if (err0) console.log(err0);
    console.log("DELETE Return ==> ");
    console.log(res0);

    //insert
    conn.query(insertSQL, function (err1, res1) {
        if (err1) console.log(err1);
        console.log("INSERT Return ==> ");
        console.log(res1);

        //query
        conn.query(selectSQL, function (err2, rows) {
            if (err2) console.log(err2);

            console.log("SELECT ==> ");
            for (var i in rows) {
                console.log(rows[i]);
            }

            //update
            conn.query(updateSQL, function (err3, res3) {
                if (err3) console.log(err3);
                console.log("UPDATE Return ==> ");
                console.log(res3);

                //query
                conn.query(selectSQL, function (err4, rows2) {
                    if (err4) console.log(err4);

                    console.log("SELECT ==> ");
                    for (var i in rows2) {
                        console.log(rows2[i]);
                    }
                });
            });
        });
    });
});

//conn.end();

직렬 작업 을 실현 하기 위해 서 모든 호출 은 callback 에서 이 루어 집 니 다. 5 층 내장 구조 입 니 다.이런 코드 는 이미 유지 할 수 없 게 되 었 다.그래서 async 라 이브 러 리 로 위의 코드 구 조 를 다시 써 야 합 니 다!
 
수 정 된 코드
var mysql = require('mysql');
var async = require('async');

var conn = mysql.createConnection({
    host: 'localhost',
    user: 'nodejs',
    password: 'nodejs',
    database: 'nodejs',
    port: 3306
});

var sqls = {
    'insertSQL': 'insert into t_user(name) values("conan"),("fens.me")',
    'selectSQL': 'select * from t_user limit 10',
    'deleteSQL': 'delete from t_user',
    'updateSQL': 'update t_user set name="conan update"  where name="conan"'
};

var tasks = ['deleteSQL', 'insertSQL', 'selectSQL', 'updateSQL', 'selectSQL'];
async.eachSeries(tasks, function (item, callback) {
    console.log(item + " ==> " + sqls[item]);
    conn.query(sqls[item], function (err, res) {
        console.log(res);
        callback(err, res);
    });
}, function (err) {
    console.log("err: " + err);
});

콘 솔 출력
deleteSQL ==> delete from t_user
{ fieldCount: 0,
  affectedRows: 0,
  insertId: 0,
  serverStatus: 34,
  warningCount: 0,
  message: '',
  protocol41: true,
  changedRows: 0 }
insertSQL ==> insert into t_user(name) values("conan"),("fens.me")
{ fieldCount: 0,
  affectedRows: 2,
  insertId: 45,
  serverStatus: 2,
  warningCount: 0,
  message: '&Records: 2  Duplicates: 0  Warnings: 0',
  protocol41: true,
  changedRows: 0 }
selectSQL ==> select * from t_user limit 10
[ { id: 45,
    name: 'conan',
    create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (      ) },
  { id: 46,
    name: 'fens.me',
    create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (      ) } ]
updateSQL ==> update t_user set name="conan update"  where name="conan"
{ fieldCount: 0,
  affectedRows: 1,
  insertId: 0,
  serverStatus: 2,
  warningCount: 0,
  message: '(Rows matched: 1  Changed: 1  Warnings: 0',
  protocol41: true,
  changedRows: 1 }
selectSQL ==> select * from t_user limit 10
[ { id: 45,
    name: 'conan update',
    create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (      ) },
  { id: 46,
    name: 'fens.me',
    create_date: Fri Sep 13 2013 12:24:51 GMT+0800 (      ) } ]
err: null

코드 의 읽 기 능력 이 배로 향상 되 었 는데 이것 이 바로 효율 적 인 개발 이다.
 
이상 원문 은 다음 과 같 습 니 다.
http://blog.fens.me/nodejs-async/
 
업무 논 리 를 처리 할 때 이러한 수요 가 있 습 니 다. 몇 개의 비동기 함수 funca, funcb funcc 를 실행 해 야 합 니 다. 모두 실행 한 후에 funcd 를 실행 해 야 합 니 다. 여 기 는 funca funcb funcc 의 실행 순서 에 대해 요구 하지 않 습 니 다. 이 를 실행 한 후에 모두 funcd 를 실행 합 니 다.async. Parallel 함 수 를 사용 할 수 있 습 니 다.
 
함수 인 터 페 이 스 는 매우 간결 하지만 이러한 기능 을 실현 했다. 그러면 문 제 는 어떻게 이런 기능 을 실현 하 는 것 입 니까?
github 의 실현 을 보면 실현 이 비교적 은밀 하고 대체적으로 이런 절차 가 있어 야 한다.
 
Var Parallel = function(array, callback) {
         Varcompleted = 0;
         비동기 함 수 를 한 번 실행 한 후, completed 가 array. length 보다 크 면, callback 을 직접 호출 하여 되 돌려 줍 니 다. completed 가 array. length 보다 작 으 면 completed 를 1 로 추가 합 니 다.
}
 
전체적으로 보면 우 리 는 업무 논리 에서 이러한 코드 를 실현 할 수 있 지만 코드 의 가 독성 과 유지 가능성 을 심각하게 낮 추 었 다.
그리고 이런 '리 턴 블랙홀' 이 나타 나 면 어 이 없 지 않 습 니까?!
doAsync1(function() {
  doAsync2(function () {
    doAsync3(function () {
      doAsync4(function () {
    })
  })
})
doAsync 1 doAsync 2 doAsync 3 doAsync 4 라 는 네 개의 비동기 함수 가 순서대로 실 행 될 수 있어 야 합 니 다. 너무 많은 코드 를 끼 워 넣 은 것 처럼 문제 가 없 을 때 도 있 습 니 다. 호출 순 서 를 제어 하기 위해 비동기 코드 가 매우 복잡 해 졌 습 니 다. 이것 이 바로 블랙홀 입 니 다. 블랙홀 이 얼마나 깊 은 지 가늠 하기에 매우 적합 한 문제 가 있 습 니 다. doAsync 2 가 doAsync 1 전에 발생 한다 면 얼마나 많은 재 구성 을 참아 야 합 니까?고통? 목 표 는 포 함 된 층수 만 줄 이 는 것 이 아니 라 모듈 화 (테스트 가능) 코드 를 작성 하여 이해 하고 수정 하 는 것 입 니 다.
async. each Series 를 사용 하면 기분 이 상쾌 하지 않 습 니까? 물론 each Series 도 결국 리 턴 체인 으로 바 뀌 어 이 루어 진 것 이 라 고 할 수 있 습 니 다. 이 루어 진 디 테 일 을 차단 한 것 에 불과 합 니 다.

좋은 웹페이지 즐겨찾기