Nodejs in the fiber (fiber) library detailed _node.js

Source: Internet
Author: User
Tags constructor garbage collection generator require

fiber/Fiber Process

In the operating system, in addition to processes and threads, there is a less applied fiber (fiber, also known as the coprocessor). Fibers are often compared to threads, and to the operating system, they are relatively lightweight operation states. Fiber turndown threads are generally considered to be lighter and less expensive. The difference is that fibers are created by threads or fibers, fiber scheduling is completely controlled by user code, for the system kernel, it is a kind of non preemptive scheduling mode, the fiber process realizes cooperative multitask, while thread and process are subject to kernel scheduling, according to priority, realize preemptive multitask. In addition, the system kernel is not aware of the specific running state of fiber, the use of fiber is actually not related to the operating system.

In node, single-threaded is only for JavaScript, and the bottom layer is actually full of multithreading. And if you need to implement multithreading in JavaScript, a common practice is to write C + + addon, bypassing JavaScript's single-threaded mechanism. However, this method increases the difficulty and cost of development and debugging. Like many other scripting languages, we can also introduce the concept of fiber into node.

Node-fibers

Node-fibers This library provides a fiber function for node. Multithreading does not test the ideal results, but in the asynchronous synchronization effect is significant, perhaps in reducing the node call stack, infinite recursion can also be valuable to dig. This document mainly describes the use of Node-fibers library and asynchronous synchronization, and so on.

Installation

Node-fibers is written in C language, direct download source code needs to compile, usually direct NPM installation can:

Copy Code code as follows:

NPM Install fibers

Use of the Fibers Library

Api

1.Fiber (FN)/new Fiber (FN):

Create a fiber that you can use as a constructor or as a normal function call. The following example:

Copy Code code as follows:

function Fibo (n) {
return n > 1? Fibo (n-1) + Fibo (n-2): 1;
}
Fiber (function () {
Console.log (Fibo (40));
});

When the run () is invoked, the fiber starts and assigns a new stack for FN, and FN runs on the new stack until FN has a return value or calls yield (). When FN Returns or calls yield (), the stack resets, and when the run () is called again, the fiber starts again, and FN runs on the first allocated stack.

2.fiber.current:

The current fiber is obtained and can be manipulated. If you specify a variable to be associated with it, be sure to ensure that the fiber is free, otherwise the V8 garbage collection mechanism ignores this part of memory and causes a memory leak.

3.fiber.yield (param):

This function has already been mentioned in the previous note. The yield () method is used to interrupt the fiber, to a certain extent, similar to return. Once yield () is executed, subsequent code in this fiber will not have a chance to execute, for example:

Copy Code code as follows:

var fiber = fiber (function () {
Console.log ("Fiber Start");
Fiber.yield ();
Console.log ("Fiber Stop");
). Run ();
Output: "Fiber Start"

After execution, only "Fiber Start" is output, and the last output command is not executed. If you pass the parameter to yield (), this argument is the return value of Run ().

Copy Code code as follows:

var fiber = fiber (function () {
Fiber.yield ("Success");
). Run ();
Console.log (fiber); -> "Success"

4.fiber.prototype.run (param):

This method has been very familiar, before vaguely mentioned call run () two tenses, one is fiber not started, when fiber was yield. In both of these tenses, the behavior of Run () is not quite the same.
When fiber is not started, run () takes a parameter and passes it to FN as its argument. When fiber handles the yielding state, run () takes a parameter and takes it as the return value of yield (), and FN does not run from the beginning, but continues from the interrupt. For the relations of FN, yield, and run, the parameters, return values, etc., can be illustrated by the following small example:

Copy Code code as follows:

var Fiber = require (' fibers ');
var fiber = fiber (function (a) {
Console.log ("First call Run:");
Console.log ("fn parameter is:" +a);
var B = Fiber.yield ("yield");
Console.log ("Second call Run:");
Console.log ("fn parameter is:" +a);
Console.log ("Yield return value is:" +b);
Return to "return";
});
Running run () for the first time
var c=fiber.run ("one");
Running run () for the second time
var d=fiber.run ("two");
Console.log ("Call Yield,run return:" +c);
Console.log ("FN run complete, run returns:" +d);

The output is as follows:

Copy Code code as follows:

/*
Call run for the first time:
The FN parameter is: one
Second call run:
The FN parameter is: one
Yield return value is: two
Call Yield,run return: Yield
FN run complete, run back: return
*/

From the example above, it is clear that yield's usage is quite different from the current JavaScript syntax. In other languages (C #, Python, etc.) have implemented the yield keyword as an iterator interrupt. You can also implement an iterator on node, specifically to understand the use of yield. Let's take the first Fibonacci sequence as an example:

Copy Code code as follows:

var fibogenerator = function () {
var a = 0, b = 0;
while (true) {
if (a = = 0) {
A = 1;
Fiber.yield (a);
} else {
B + A;
b = = a? A = 1:a = B-a;
Fiber.yield (b);
}
}
}
var f = new Fiber (fibogenerator);
F.next = F.run;
for (var i = 0; i < i++) {
Console.log (F.next ());
}

The output is:

Copy Code code as follows:

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

There are two issues to pay attention to, first, yield said is the method, more like the keyword, and run different, yield do not need to rely on fiber instances, and run is needed. If you call run inside Fiber, be sure to use: Fiber.current.run (), and second, yield reserved keywords that are JavaScript and are not sure if and when they will be enabled, so the code may face changes in the future.

5.fiber.prototype.reset ():

We already know that fiber may exist in different tenses and affect the behavior of run. The Reset method returns to its original state regardless of what state the fiber handles. Then run again, and then the FN is rerun.

6.fiber.prototype.throwinto (Exception):

Essentially, Throwinto throws the exception passed to it and takes the exception information as the return value of run. If the exception being thrown in the fiber is not handled, the exception will continue to bubble. Regardless of whether the exception is handled, it forces yield and interrupts fiber.

Use of the Future library

It is not always reasonable to use fiber directly in node because the fiber API is so simple that it will inevitably produce repetitive, lengthy code in actual use, which is not conducive to maintenance. It is recommended to add a layer of abstraction between node and fiber so that fiber can work better. The future library provides such an abstraction. Future libraries or any level of abstraction may not be perfect, no one is right or wrong, only the application does not apply. For example, the future library provides us with a simple API to do asynchronous synchronization, but it does nothing to encapsulate generator (like the Fibonacci sequence generator above).

The future library does not need to download the installation separately, it is already included in the fibers library, only the Var future=require (' Fibers/future ') is required for use.

Api

1.function.prototype.future ():

Adds a future method to the function type to convert the function to a "funture-function".

Copy Code code as follows:

var futurefun = function Power (a) {
Return a * A;
}.future ();
Console.log (futurefun). Wait ());

In fact, the power method is executed within the Fibel. However, the existing version of the future has bugs, the official does not specify, if you need to use this feature, please delete the future.js line No. 339 and line No. 350.

2.new Future ()

The constructor for the future object, described in detail below.

3.future.wrap (FN, IDX)

The Wrap method encapsulates asynchronous synchronous operation, which is the most valuable method in future library. FN represents the function that needs to be converted, IDX represents the number of parameters the FN accepts, and considers its callback method to be the last parameter (this API is controversial, some people tend to pass callback should be in the position, fortunately wrap method is relatively simple, you can easily modify the code). Look at an example to understand the use of wrap:

Copy Code code as follows:

var readfilesync = Future.wrap (Require ("FS"). ReadFile);
Fiber (function () {
var html = Readfilesync ("./1.txt"). Wait (). toString ();
Console.log (HTML);
). Run ();

As you can see from this example, fiber asynchronous sync is really effective, except for a more grammatical step. Wait () outside, other already FS provides Fs.readfilesync method identical.

4.future.wait (Futures):

This method has been seen several times before. As the name suggests, its role is to wait for results. If you want to wait for the result of a Future instance, call Futureinstance.wait () directly, or call future.wait (Futuresarray) If you need to wait for the results of a series of Future instances. It should be noted that in the second usage, a future instance has an error at run time, and the wait method does not throw an error, but we can use the Get () method to obtain the run results directly.

5.future.prototype.get ():

The use of Get () is much like the first method of Wait (), and the difference is that get () immediately returns the result. If the data is not ready, get () throws an error.

6.future.prototype.resolve (PARAM1,PARAM2):

The Wrap method above always gives people a callback function that future actually swallows the asynchronous method and returns the asynchronous result directly. In fact future also provides a solution for setting callback functions through the Resolve method. Resolve accepts up to two parameters, and if only one argument is passed, future thinks a node-style callback function is passed, such as the following example:

Copy Code code as follows:

Futureinstance.resolve (function (err, data) {
if (err) {
throw err;
} else {
Console.log (Data.tostring ());
}
});

If two parameters are passed in, the error and data are treated separately, as shown in the following example:

Copy Code code as follows:

Futureinstance.resolve (function (err) {
throw err;
}, function (data) {
Console.log (Data.tostring ());
});

In addition, future does not distinguish between the timing of resolve invocation, if the data is not ready, then the callback function into the queue, by the resolver () method of unified scheduling, or directly fetch data immediately execute the callback function.

7.future.prototype.isresolved ():

Returns a Boolean value that indicates whether the operation has been performed.

8.future.prototype.proxy (futureinstance):

The proxy method provides a proxy for a future instance, which is essentially a wrapper over the Resolve method, in fact, a instance callback method as another instance callback performer. For example:

Copy Code code as follows:

var target = new Future;
Target.resolve (function (err, data) {
Console.log (data)
});
var proxyfun = function (num, CB) {
CB (NULL, num * num);
};
Fiber (function () {
var proxy = Future.wrap (Proxyfun) (10);
Proxy.proxy (target);
). Run (); Output 100

Although the execution is proxy, the final target's callback function executes and is the callback function that drives target with the execution result of proxy. This kind of proxy means may have the very big effect in our practical application, I have not thought deeply in the meantime.

9.future.prototype.return (value):

10.future.prototype.throw (Error):

11.future.prototype.resolver ():

12.future.prototype.detach ():

The above four APIs I feel relative to other APIs, the actual use of the scene or the role is more general. Return and throw are resolver method of scheduling, these three methods are very important, in the normal future use process will silently work, but I did not come up with the specific use of their own scene, so there is no way to specifically introduce. The detach method can only be counted as a simplified version of Resolve method, and it is not necessary to introduce.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.