>웹 프론트엔드 >JS 튜토리얼 >nodejs_node.js의 Fiber(파이버) 라이브러리에 대한 자세한 설명

nodejs_node.js의 Fiber(파이버) 라이브러리에 대한 자세한 설명

WBOY
WBOY원래의
2016-05-16 16:07:511642검색

섬유/섬유

운영 체제에는 프로세스와 스레드 외에 거의 사용되지 않는 파이버(파이버, 코루틴이라고도 함)의 종류도 있습니다. 파이버는 종종 스레드와 비교되며 운영 체제에서는 둘 다 경량 실행 상태입니다. 파이버는 일반적으로 스레드보다 가볍고 오버헤드가 적은 것으로 간주됩니다. 차이점은 파이버가 스레드 또는 파이버에 의해 생성되고 파이버 스케줄링이 사용자 코드에 의해 완전히 제어된다는 점입니다. 시스템 커널의 경우 파이버는 스레드와 프로세스를 통해 스케줄링됩니다. 커널을 구성하고 우선순위에 따라 선점형 멀티태스킹을 구현합니다. 또한 시스템 커널은 광케이블의 구체적인 실행 상태를 알지 못하며 광케이블의 사용은 실제로 운영 체제와 상대적으로 독립적입니다.

노드에서 단일 스레드는 자바스크립트 전용이며, 그 하위 레이어는 실제로 멀티 스레드로 가득 차 있습니다. JavaScript에서 멀티스레딩을 구현해야 하는 경우 일반적인 접근 방식은 JavaScript의 단일 스레드 메커니즘을 우회하는 C 애드온을 작성하는 것입니다. 그러나 이 방법은 개발 및 디버깅의 어려움과 비용을 증가시킵니다. 다른 많은 스크립팅 언어와 마찬가지로 노드에 파이버 개념을 도입할 수도 있습니다.

노드 파이버

node-fibres 라이브러리는 node에 대한 Fiber 기능을 제공합니다. 멀티스레딩 테스트는 이상적인 결과를 얻지는 못했지만 비동기식을 동기식으로 변환하는 데 상당한 효과가 있으며 노드 호출 스택 및 무한 재귀를 줄이는 데도 유용할 수 있습니다. 이 문서에서는 주로 node-fibres 라이브러리를 사용하는 방법과 비동기식에서 동기식으로의 변환 방법을 소개합니다.

설치

node-fibres는 C 언어로 작성되었습니다. 소스 코드를 직접 다운로드하려면 컴파일이 필요합니다. 일반적으로 npm을 사용하여 직접 설치할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

npm 설치 파이버

섬유 라이브러리 활용

API

1.Fiber(fn)/새 Fiber(fn):

생성자로 사용하거나 일반 함수로 호출할 수 있는 파이버를 만듭니다. 예:

코드 복사 코드는 다음과 같습니다.

함수 fibo(n) {
n > 1 ? fibo(n - 1) fibo(n - 2) : 1;
}
섬유(함수 () {
console.log(fibo(40));
});

run()이 호출되면 파이버가 시작되고 fn에 대한 새 스택을 할당합니다. fn은 반환 값을 갖거나 Yield()가 호출될 때까지 이 새 스택에서 실행됩니다. fn이 Yield()를 반환하거나 호출한 후 스택이 재설정됩니다. run()이 다시 호출되면 파이버가 다시 시작되고 fn은 처음 할당된 스택에서 실행됩니다.

2.Fiber.current:

현재 광섬유를 가져와서 작동해 보세요. 연관될 변수를 지정하는 경우 이 파이버가 해제될 수 있는지 확인하십시오. 그렇지 않으면 V8의 가비지 수집 메커니즘은 항상 메모리의 이 부분을 무시하여 메모리 누수를 유발합니다.

3.Fiber.yield(매개변수):

이 기능은 이전 설명에서 언급한 바 있습니다. Yield() 메서드는 파이버를 중단하는 데 사용되며, 이는 어느 정도 반환되는 것과 유사합니다. 일단 Yield()가 실행되면 이 Fiber의 후속 코드는 실행될 기회가 없습니다. 예:

코드 복사 코드는 다음과 같습니다.

var 섬유 = 섬유(함수 () {
console.log("Fiber 시작");
Fiber.yield();
console.log("광섬유 중지");
}).run();
// 출력: "Fiber 시작"

실행 후에는 "Fiber Start"만 출력되고, 후자의 출력 명령은 실행되지 않습니다. 매개변수가 Yield()에 전달되면 이 매개변수는 run()의 반환 값으로 사용됩니다.

코드 복사 코드는 다음과 같습니다.

var 섬유 = 섬유(함수 () {
Fiber.yield("성공");
}).run();
console.log(섬유); // -> "성공"

4.Fiber.prototype.run(param):

이 방법은 이미 매우 익숙합니다. 앞서 언급한 run() 호출에는 두 가지 시제가 있는데, 하나는 Fiber가 시작되지 않는 경우이고 다른 하나는 Fiber가 생성되는 경우입니다. run()의 동작은 이 두 시제에서 동일하지 않습니다.
Fiber가 시작되지 않으면 run()은 인수를 받아들이고 이를 인수로 fn에 전달합니다. Fiber가 항복 상태를 처리할 때 run()은 매개변수를 받아들이고 이를 항복()의 반환 값으로 사용합니다. fn은 처음부터 실행되지 않고 중단된 지점부터 계속 실행됩니다. fn, Yield, run의 매개변수와 반환 값 간의 관계는 다음과 같은 간단한 예를 통해 설명할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

var Fiber = require('섬유');
var 섬유 = 섬유(함수 (a) {
console.log("첫 번째 호출 실행:");
console.log("fn 매개변수는: " a);
var b = Fiber.yield("수율");
console.log("두 번째 호출 실행:");
console.log("fn 매개변수는: " a);
console.log("수익률 반환 값: " b);
"반품"을 반환합니다;
});
// 첫 번째 실행 run()
var c=섬유.run("하나");
//run()
을 두 번째로 실행합니다. var d=섬유.run("2");
console.log("yield 호출, 실행 반환: " c);
console.log("fn 작업이 완료되고 실행이 반환됩니다: " d);

출력은 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

/*
처음으로 run을 호출할 때:
fn 매개변수는 다음과 같습니다: One
실행 호출:
두 번째 fn 매개변수는 다음과 같습니다: One
Yield의 반환 값은 다음과 같습니다. Two
Yield 호출, 반환 실행: Yield
fn이 완료되고 실행이 반환됩니다: return
*/

위의 예를 보면 현재 JavaScript 구문과 Yield의 사용법이 상당히 다르다는 것이 분명합니다. Yield 키워드는 다른 언어(C#, Python 등)에서 반복자에 대한 인터럽트로 구현되었습니다. 노드에 반복자를 구현하고 Yield의 사용을 자세히 경험할 수도 있습니다. 시작 부분의 피보나치 수열을 예로 들어 보겠습니다.

코드 복사 코드는 다음과 같습니다.

var fiboGenerator = 함수 () {
var a = 0, b = 0;
동안 (사실) {
If (a == 0) {
            a = 1;
Fiber.yield(a);
         } else {
              b = a;
                b == a ? a = 1 : a = b - a;
Fiber.yield(b);
}
}
}
var f = 새로운 Fiber(fiboGenerator);
f.next = f.run;
for (var i = 0; i console.log(f.next());
}

출력은 다음과 같습니다.

코드 복사 코드는 다음과 같습니다.

/*
1
1
2
3
5
8
13
21
34
55
*/

주의해야 할 두 가지 문제가 있습니다. 첫째, Yield는 키워드와 유사한 메서드라고 합니다. Yield는 Run과 달리 Fiber 인스턴스에 의존할 필요가 없습니다. Fiber 내부에서 run을 호출하는 경우 다음을 사용해야 합니다. Fiber.current.run(); 둘째, Yield 자체는 JavaScript의 예약된 키워드입니다. 활성화 여부와 시기가 확실하지 않으므로 코드가 변경될 수 있습니다. 미래. .

5.Fiber.prototype.reset():

우리는 Fiber가 다양한 시제를 가질 수 있으며 이는 달리기 동작에도 영향을 미칠 수 있다는 것을 이미 알고 있습니다. 재설정 방법은 Fiber가 어떤 상태를 처리하든 상관없이 초기 상태로 돌아갑니다. 이후 실행 실행은 fn을 다시 실행합니다.

6.Fiber.prototype.throwInto(예외):

기본적으로 throwInto는 전달된 예외를 발생시키고 예외 정보를 실행의 반환 값으로 사용합니다. 발생한 예외가 Fiber에서 처리되지 않으면 예외가 계속해서 발생합니다. 예외 처리 여부에 관계없이 강제로 항복이 발생하고 Fiber가 중단됩니다.

미래도서관 활용

Fiber의 API는 실제로 매우 간단하기 때문에 Fiber를 노드에서 직접 사용하는 것이 항상 합리적인 것은 아닙니다. 실제로 사용하면 필연적으로 반복적이고 긴 코드가 생성되어 유지 관리에 도움이 되지 않습니다. Fiber가 더 잘 작동할 수 있도록 노드와 Fiber 사이에 추상화 계층을 추가하는 것이 좋습니다. 미래 라이브러리는 이러한 추상화를 제공합니다. 미래의 라이브러리나 추상화 수준은 완벽하지 않을 수 있습니다. 옳고 그름은 없으며, 적용 가능한 것과 그렇지 않은 것만이 있을 뿐입니다. 예를 들어 future 라이브러리는 비동기에서 동기로의 작업을 완료할 수 있는 간단한 API를 제공하지만 생성기를 캡슐화하는 작업은 수행할 수 없습니다(위의 Fibonacci 시퀀스 생성기와 유사).

future 라이브러리는 별도로 다운로드하여 설치할 필요가 없습니다. Fibers 라이브러리에 이미 포함되어 있으므로 사용 시에는 var future=require('fibres/future')만 있으면 됩니다.

API

1.Function.prototype.future():

함수 유형에 future 메서드를 추가하여 함수를 "funture-function"으로 변환합니다.

코드 복사 코드는 다음과 같습니다.

var futureFun = 함수 전력(a) {
*a를 반환합니다;
}.future();
console.log(futureFun(10).wait());

실제로 Power Method는 Fibel 내에서 실행됩니다. 하지만 기존 버전의 future에는 버그가 있으며 공식적인 공식적인 설명이 없습니다. 이 기능을 사용해야 하는 경우 future.js의 339행과 350행을 삭제하세요.

2.new Future()

아래에 자세히 설명된 Future 개체의 생성자입니다.

3.Future.wrap(fn, idx)

랩 방법은 비동기식에서 동기식 작업을 캡슐화하며 미래 라이브러리에서 우리에게 가장 가치 있는 방법입니다. fn은 변환해야 하는 함수를 나타내고, idx는 fn이 허용하는 매개변수 수를 나타내며, 콜백 메소드는 마지막 매개변수로 간주됩니다(여기서 API의 공식화는 논란의 여지가 있습니다. 어떤 사람들은 다음 위치를 전달하는 경향이 있습니다. 다행히도 Wrap 메서드는 비교적 간단하고 코드를 수정하기가 더 쉽습니다. 다음 예를 보면 Wrap의 사용법을 이해할 수 있습니다.

코드 복사 코드는 다음과 같습니다.

var readFileSync = Future.wrap(require("fs").readFile);
섬유(함수 () {
var html = readFileSync("./1.txt").wait().toString();
console.log(html);
}).run();

이 예에서 Fiber 비동기식에서 동기식으로의 변환이 실제로 매우 효과적이라는 것을 알 수 있습니다. 구문의 추가 단계 .wait()를 제외하면 fs에서 이미 제공하는 다른 fs.readFileSync 메서드는 동일합니다.

4.Future.wait(선물):

이러한 방법은 이전에도 여러 번 목격되었습니다. 이름에서 알 수 있듯이 그 기능은 결과를 기다리는 것입니다. 미래 인스턴스의 결과를 기다리려면 futureInstance.wait()를 직접 호출하세요. 일련의 미래 인스턴스 결과를 기다려야 한다면 Future.wait(futuresArray)를 호출하세요. 두 번째 사용법에서는 향후 인스턴스가 실행될 때 오류가 발생하면 wait 메서드는 오류를 발생시키지 않지만 get() 메서드를 사용하여 실행 결과를 직접 얻을 수 있습니다.

5.Future.prototype.get():

get()의 사용법은 wait()의 첫 번째 메소드와 매우 유사합니다. 차이점은 get()이 결과를 즉시 반환한다는 것입니다. 데이터가 준비되지 않은 경우 get()은 오류를 발생시킵니다.

6.Future.prototype.resolve(param1,param2):

위의 랩 메소드는 항상 사람들에게 future가 실제로 비동기 메소드의 콜백 함수를 삼키고 비동기 결과를 직접 반환한다는 인상을 줍니다. 실제로 future는 해결 메소드를 통해 콜백 함수를 설정하는 솔루션도 제공합니다. 해결은 최대 2개의 매개변수를 허용합니다. 하나의 매개변수만 전달되면 future는 다음 예와 같이 노드 스타일 콜백 함수가 전달된 것으로 간주합니다.

코드 복사 코드는 다음과 같습니다.

futureInstance.resolve(함수(err, data) {
만약 (오류) {
           오류를 던집니다.
} 그 밖의 {
console.log(data.toString());
}
});

두 개의 매개변수가 전달되면 오류와 데이터가 별도로 처리된다는 의미입니다.

코드 복사 코드는 다음과 같습니다.

futureInstance.resolve(함수 (err) {
던지기 오류;
}, 함수(데이터) {
console.log(data.toString());
});

또한 future는 Resolve의 호출 시점을 구분하지 않습니다. 데이터가 준비되지 않은 경우 콜백 함수가 대기열에 푸시되고 Resolver() 메서드에 의해 균일하게 예약됩니다. 그렇지 않으면 데이터를 직접 가져옵니다. 콜백 함수가 즉시 실행됩니다.

7.Future.prototype.isResolved():

작업이 수행되었는지 여부를 나타내는 부울 값을 반환합니다.

8.Future.prototype.proxy(futureInstance):

프록시 메소드는 본질적으로 해결 메소드의 래퍼인 미래 인스턴스에 대한 프록시를 제공합니다. 실제로 한 인스턴스의 콜백 메소드를 다른 인스턴스의 콜백 실행자로 사용합니다. 예:

코드 복사 코드는 다음과 같습니다.

var target = 새로운 Future;
target.resolve(함수 (err, data) {
console.log(데이터)
});
var ProxyFun = 함수(숫자, cb) {
cb(null, num * num);
};
섬유(함수 () {
var 프록시 = Future.wrap(proxyFun)(10);
Proxy.proxy(대상);
}).run(); // 100을 출력

프록시가 실행되더라도 결국에는 대상의 콜백 함수가 실행되고, 프록시의 실행 결과에 따라 대상의 콜백 함수가 구동됩니다. 이 프록시 방법은 실제 응용 프로그램에서 큰 역할을 할 수 있지만 아직 깊이 생각해 보지 않았습니다.

9.Future.prototype.return(값):

10.Future.prototype.throw(오류):

11.Future.prototype.resolver():

12.Future.prototype.detach():

위 4가지 API의 경우 다른 API에 비해 실제 사용 시나리오나 기능은 상대적으로 평균적이라고 생각합니다. return과 throw는 모두 리졸버 메서드에 의해 예약됩니다. 이 세 가지 메서드는 매우 중요하며 일반적인 향후 사용 프로세스에서 자동으로 작동합니다. 그러나 별도로 사용하는 구체적인 시나리오를 파악하지 못했기 때문에 소개할 방법이 없습니다. 상세히. Detach 방식은 Resolve 방식의 단순화된 버전으로만 간주할 수 있으므로 도입할 필요는 없습니다.

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.