NodeJs 병렬 비동기 처리

7274 단어
여기 서 비동기 라 고 하 는 것 은 정확 하지 않 으 니 연속 비동기 라 고 해 야 한다.NodeJs 단일 스 레 드 비동기 의 특성 으로 여러 비동기 가 동시에 진행 되 었 을 때 마지막 실행 결 과 를 확인 할 수 없습니다.간단 한 예 를 들다.
for(var i = 0; i < 5; i++) {
    fs.readFile('file', 'utf-8', function(error, data){});
}

5 번 연속 으로 파일 을 읽 는 비동기 작업 을 시 작 했 습 니 다. 간단 합 니 다. 그러면 문제 가 생 겼 습 니 다. 모든 비동기 가 다 실 행 된 것 을 어떻게 확인 합 니까?그것들 이 모두 실 행 된 후에 야 이후 의 조작 을 할 수 있 기 때문이다.약간의 경험 이 있 는 학우 들 은 모두 기 수 를 사용 하 는 방식 으로 진행 할 것 이 라 고 믿 지만, 어떻게 기수 가 정확 하 다 고 보장 하 느 냐 가 또 하나의 문제 이다.곰 곰 이 생각해 보면:
리 셋 은 하나의 함수 입 니 다. 모든 비동기 작업 을 할 때 계수 기 를 + 1 하고 모든 비동기 가 끝 날 때 계수 기 를 - 1 로 합 니 다. 카운터 가 0 인지 여 부 를 판단 하여 리 셋 을 실행 할 지 여 부 를 확인 합 니 다.이 논 리 는 매우 간단 합 니 다. 실행 시 와 리 셋 시 에 비해 전역 변 수 를 카운터 로 해 야 합 니 다. 또한 비동기 방법 은 + 1 동작 을 수행 하 는 것 입 니 다. 그리고 그 다음 에 리 셋 할 함수 로 되 돌아 갑 니 다. 약간 돌아 갑 니 다. 하지만 Js 함수 의 고급 용법 을 보 세 요.
var pending = (function() {
    var count = 0;
    return function() {
        count++;
        return function() {
            count--;
            if (count === 0) {
                //       
            }
        }
    }
});

pending 호출 시 pending (), 예 를 들 어:
var done = pending();

이 때 계수 변수 count 는 0 으로 초기 화 되 고 돌아 오 는 함수 가 done 에 붙 어 있 습 니 다. 이때 done () 을 실행 하면 무엇 입 니까?pending 이 되 돌아 오 는 첫 번 째 함 수 를 직접 실행 하 는 것 이 아 닙 니까? 즉, pending () () 입 니 다. 이 실행 은 무엇 입 니까? 먼저 계수 변 수 를 count + 1 로 되 돌려 주 었 습 니 다. 이 함 수 는 직접 callback 으로 비동기 로 전달 하 는 방법 입 니 다. 이 callback 을 실행 할 때 먼저 계수 변 수 를 count - 1 로 계산 하고 count 가 0 인지 판단 합 니 다.0 이면 모든 비동기 실행 이 완료 되 었 음 을 나타 내 고 연속 적 인 비동기, 같은 반전 작업 에 도달 합 니 다.
관건 은 두 개의 return 에 있다. 간단하게 말 하면:
첫 번 째 return 함 수 는 count + 1 을 다음 에 되 돌려 야 할 함수 로 되 돌려 줍 니 다.
두 번 째 return 의 함 수 는 바로 리 셋 이 필요 한 함수 입 니 다. 만약 에 실행 하면 count - 1 을 한 다음 에 비동기 가 모두 실행 되 었 는 지, 완성 되 었 는 지 판단 하면 리 셋 합 니 다.
실제 점 의 예 를 보고 여러 파일 의 비동기 반전 을 읽 습 니 다.
var fileName = ['1.html', '2.html', '3.html'];

var done = pending(function(fileData) {
    console.log('done');
    console.log(fielData);
});

for(var i = 0; i < fileName.lenght; i++) {
    fs.readFile(fileName[i], 'utf-8', done(fileName[i]));
}

그 중의 done, 즉 pending 방법 으로 우리 가 실행 하고 싶 은 방법 을 감 쌌 습 니 다. 카운터 가 0 일 때 그것 을 실행 합 니 다. 그러면 우 리 는 pending 방법 을 개선 해 야 합 니 다.
var pending = (function(callback) {
    var count = 0;
    var returns = {};

    console.log(count);
    return function(key) {
        count++;
        console.log(count);
        return function(error, data) {
            count--;
            console.log(count);
            returns[key] = data;
            if (count === 0) {
                callback(returns);
            }
        }
    }
});

콜백 은 우리 의 리 턴 함수 입 니 다. var done = pending (callback) 일 때 done 은 첫 번 째 return 함수 입 니 다. 되 돌아 오 는 값 의 아래 표 시 를 할 수 있 는 인자 가 있 기 때문에 순환 체 에서 done (fileName [i]) 에서 파일 이름 을 전달 합 니 다.이 done () 은 직접 실 행 됩 니 다. count + 1 후 비동기 방법 에 전 할 리 셋 함 수 를 되 돌려 줍 니 다. 앞에서 말 한 바 와 같이 이 리 셋 함 수 는 계수 변수 에 따라 우리 가 실행 하고 자 하 는 리 셋 함 수 를 실행 할 지 여 부 를 판단 하고 파일 의 내용 을 리 턴 스 로 전달 합 니 다.자, 운행 해 보 세 요. 운행 결 과 를 정확하게 볼 수 있 을 거 라 고 믿 습 니 다.
0
1
2
3
2
1
0
done
{"1.html": "xxx", "2.html": "xxx", "3.html": "xxx"}

계산 에서 알 수 있 듯 이 0 - 3 에서 0 까지 그 다음 에 우리 의 반전 함수 가 done 과 파일 의 내용 을 출력 했다.
이 문 제 는 해결 되 었 습 니 다. 우 리 는 어떻게 이런 방법 을 포장 하여 중용 시 킬 수 있 는 지 생각해 야 합 니 다. 그렇지 않 으 면 매번 pending 을 쓰 는 것 은 매우 비 과학적 이지 않 습 니까?
다음은 UnJs (NodeJs 기반 웹 개발 프레임 워 크) 의 처리 방식 을 살 펴 보 겠 습 니 다. 템 플 릿 분석 에 사용 되 는 하위 템 플 릿 작업:
unjs.asyncSeries = function(task, func, callback) {
    var taskLen = task.length;
    if (taskLen <= 0) {
        return;
    }

    var done = unjs.pending(callback);
    for(var i = 0; i < taskLen; i++) {
        func(task[i], done);
    }
}

asyncSeries 에는 세 개의 인자 가 있 습 니 다.
task: 읽 어야 할 파일 과 같은 처리 대상 은 목록 입 니 다. 목록 이 아니 거나 목록 길이 가 0 이면 실행 되 지 않 습 니 다.
func: 비동기 방법, 예 를 들 어 fs. readFile 은 이 를 통 해 전 달 된 것 입 니 다.
콜백: 우리 가 원 하 는 방법
done 은 앞 과 같 습 니 다. func 에 전 달 했 지만 실행 되 지 않 았 습 니 다. 응용 단 이 파 라 메 터 를 제어 할 수 있 기 를 원 하기 때문에 응용 단 을 실행 하 게 합 니 다.
하위 템 플 릿 을 처리 할 때의 동작 을 다시 봅 니 다:
var subTemplate = [];
var patt = /\{\% include \'(.+)\' \%\}/ig;
while(sub = patt.exec(data)) {
    var subs = sub;
    subTemplate.push([subs[0], subs[1]]);
}

unjs.asyncSeries(subTemplate, function(item, callback) {
    fs.readFile('./template/' + item[1], 'utf-8', callback(item[0]));
}, function(data) {
    for(var key in data) {
        html = html.replace(key, data[key]);
    }
});

subTemplate 이 목록 은 하위 템 플 릿 에 대한 분석 에 따라 생 성 된 데이터 입 니 다. 2 차원 배열 입 니 다. 각 하위 항목 의 첫 번 째 값 은 하위 템 플 릿 의 호출 텍스트 입 니 다. 즉, {% include 'header. html'%} 과 같은 문자열 입 니 다. 두 번 째 매개 변 수 는 하위 템 플 릿 파일 이름 입 니 다. 즉, header. html 입 니 다.
asyncSeries 의 두 번 째 매개 변 수 는 callback 입 니 다. 실제 세 번 째 매개 변수 입 니 다. 즉, 우리 가 실행 하고 자 하 는 리 셋 함수 가 pending 처 리 를 거 친 리 셋 방법 입 니 다. 앞에서 말 한 바 와 같이 asyncSeries 내부 에서 실행 되 지 않 고 여기 서 실 행 됩 니 다. 즉, callback (item [0]) 은 인 자 를 가 져 왔 습 니 다.이 매개 변수 에 따라 부모 템 플 릿 에서 하위 템 플 릿 을 호출 하 는 문자열 을 하위 템 플 릿 의 내용 으로 바 꿔 야 하기 때 문 입 니 다.
이렇게 하면 연속 비동기 가 필요 할 때 asyncSeries 방법 으로 처리 할 수 있다.비동기 적 인 관계 로 인해 프로그램의 절차 가 약간 복잡 하고 이해 하기 어 려 울 수도 있 습 니 다. 익숙 하 더 라 도 갑자기 이해 하지 못 할 수도 있 습 니 다. 괜 찮 습 니 다. 예 를 들 어 두 번 째 매개 변수 중의 콜 백 은 실제 세 번 째 매개 변수 로 생 성 되 었 습 니 다. 처음에 이 콜 백 은 도대체 무엇 인지 생각 할 수 있 습 니 다.그리고 pending 의 return 두 개 도 이해 하기 어 려 우 니 많이 생각해 보 세 요.
자, 연속 비동기 리 셋 은 Js 함수 의 고급 특성 을 사용 하여 완성 되 었 습 니 다.그러나 NodeJs 의 비동기 성 은 프로그램의 통 제 를 매우 문제 로 만 들 었 다. 예 를 들 어 연속 적 인 비동기 가 있 지만 값 을 전달 하 는 조작 등 은 모두 이런 사고방식 을 통 해 변화 시 키 면 실현 할 수 있다.
이 글 은 NodeJs 의 비동기 조작 으로 어 지 러 운 학생 들 에 게 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기