亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 語言 > JavaScript > 正文

nodejs中的fiber(纖程)庫詳解

2024-05-06 16:17:32
字體:
來源:轉載
供稿:網友
這篇文章主要介紹了nodejs中的fiber(纖程)庫詳解,本文講解了node-fibers的安裝、API介紹、方法使用示例等內容,需要的朋友可以參考下
 

fiber/纖程

在操作系統中,除了進程和線程外,還有一種較少應用的纖程(fiber,也叫協程)。纖程常常拿來跟線程做對比,對于操作系統而言,它們都是較輕量級的運行態。通常認為纖程比線程更為輕量,開銷更小。不同之處在于,纖程是由線程或纖程創建的,纖程調度完全由用戶代碼控制,對系統內核而言,是一種非搶占性的調度方式,纖程實現了合作式的多任務;而線程和進程則受內核調度,依照優先級,實現了搶占式的多任務。另外,系統內核是不知道纖程的具體運行狀態,纖程的使用其實是比較與操作系統無關。

在node中,單線程是僅針對javascript而言的,其底層其實充斥著多線程。而如果需要在javascript中實現多線程,一種常見的做法是編寫C++ addon,繞過javascript的單線程機制。不過這種方法提升了開發調試的難度和成本。像其他很多腳本語言,我們也可以把纖程的概念引入到node中。

node-fibers

node-fibers這個庫就為node提供了纖程的功能。多線程方面沒有測試出理想的結果,不過在異步轉同步作用顯著,也許在減少node調用堆棧、無限遞歸方面也會有價值可挖。本文檔主要介紹 node-fibers庫的使用方法和異步轉同步等內容。

安裝

node-fibers是采用C語言編寫,直接下載源碼需要編譯,通常直接npm安裝即可:

復制代碼代碼如下:

npm install fibers

 

fibers庫的使用

API

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

創建一個纖程,可以當成構造函數使用,也可以當成普通函數調用。如下例:

復制代碼代碼如下:

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

 

當 run()調用的時候,纖程啟動,并為 fn分配新的堆棧, fn會在這個新的堆棧上運行,直到 fn有返回值或調用 yield()。 fn返回后或調用 yield()后,堆棧重置,當再次調用 run()時,纖程會再次啟動, fn運行于首次分配的堆棧中。

2.Fiber.current:

獲得當前纖程,并可對其進行操作。如果指定一個變量與其相關聯,請務必確保此纖程能夠釋放,否則V8的垃圾回收機制會一直忽略這部分的內存,造成內存泄漏。

3.Fiber.yield(param):

前面的說明中已經提及過這個函數。 yield()方法用于中斷纖程,一定程度上類似 return。一旦執行 yield(),則此 Fiber中后續代碼將沒有機會執行,例如:

 

復制代碼代碼如下:

var fiber = Fiber(function () {
    console.log("Fiber Start");
    Fiber.yield();
    console.log("Fiber Stop");
}).run();
// 輸出: "Fiber Start"

 

執行后只會輸出“Fiber Start”,后一個輸出命令沒有執行。如果向 yield()傳入參數,那么此參數作為 run()的返回值。

復制代碼代碼如下:

var fiber = Fiber(function () {
    Fiber.yield("success");
}).run();
console.log(fiber); // -> "success"

 

4.Fiber.prototype.run(param):

這個方法已經很熟悉了,之前隱約有提及調用 run()的兩種時態,一是Fiber未啟動時,一時Fiber被yield時。在這兩種時態下, run()的行為并不太一樣。
當Fiber未啟動時, run()接受一個參數,并把它傳遞給 fn,作為其參數。當Fiber處理yielding狀態時, run()接受一個參數,并把它作為 yield()的返回值,fn并不會從頭運行,而是從中斷處繼續運行。關于 fn、 yield、 run三者的參數、返回值等關系,可以通過下面的小例子來說明:

 

復制代碼代碼如下:

var Fiber = require('fibers');
var fiber = Fiber(function (a) {
    console.log("第一次調用run:");
    console.log("fn參數為:"+a);
    var b = Fiber.yield("yield");
    console.log("第二次調用run:");
    console.log("fn參數為:"+a);
    console.log("yield返回值為:"+b);
    return "return";
});
// 第一次運行run()
var c=fiber.run("One");
// 第二次運行run()
var d=fiber.run("Two");
console.log("調用yield,run返回:"+c);
console.log("fn運行完成,run返回:"+d);

 

輸出如下:

 

復制代碼代碼如下:

/*
第一次調用run:
fn參數為:One
第二次調用run:
fn參數為:One
yield返回值為:Two
調用yield,run返回:yield
fn運行完成,run返回:return
*/

 

從上面例子中,可以很明顯看出 yield的使用方法與現在的javascript的語法相當不同。在別的語言中(C#、Python等)已經實現了 yield關鍵字,作為迭代器的中斷。不妨在node上也實現一個迭代器,具體體會一下 yield的使用。還是以開頭的斐波那契數列為例:

復制代碼代碼如下:

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 < 10; i++) {
    console.log(f.next());
}

 

輸出為:

復制代碼代碼如下:

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

 

有兩個問題需要留意,第一, yield說是方法,更多地像關鍵字,與 run不同, yield不需要依托Fiber實例,而 run則需要。如果在Fiber內部調用 run,則一定要使用: Fiber.current.run();第二, yield本身為javascript的保留關鍵字,不確定是否會、何時會啟用,所以代碼在將來可能會面臨變更。

5.Fiber.prototype.reset():

我們已經知道Fiber可能存在不同的時態,同時會影響 run的行為。而 reset方法則不管Fiber處理什么狀態,都恢復到初始狀態。隨后再執行 run,就會重新運行 fn。

6.Fiber.prototype.throwInto(Exception):

本質上 throwInto會拋出傳給它的異常,并將異常信息作為 run的返回值。如果在Fiber內不對它拋出的異常作處理,異常會繼續冒泡。不管異常是否處理,它會強制 yield,中斷Fiber。

future庫的使用

在node中直接使用Fiber并不一直是合理的,因為Fiber的API實在簡單,實際使用中難免會產生重復冗長的代碼,不利于維護。推薦在node與Fiber之間增加一層抽象,讓Fiber能夠更好地工作。 future庫就提供了這樣一種抽象。 future庫或者任何一層抽象也許都不是完美的,沒有誰對誰錯,只有適用不適用。比如, future庫向我們提供了簡單的API能夠完成異步轉同步的工作,然而它對封裝 generator (類似上面的斐波那契數列生成器)則無能為力。

future庫不需要單獨下載安裝,已經包含在 fibers庫中,使用時只需要 var future=require('fibers/future') 即可。

API

1.Function.prototype.future():

給 Function類型添加了 future方法,將function轉化成一個“funture-function”。

復制代碼代碼如下:

var futureFun = function power(a) {
    return a * a;
}.future();
console.log(futureFun(10).wait());

 

實際上 power方法是在Fibel內執行的。不過現有版本的 future有bug,官方沒有具體的說明,如果需要使用此功能,請刪除掉 future.js的第339行和第350行。

2.new Future()

Future對象的構造函數,下文詳細介紹。

3.Future.wrap(fn, idx)

wrap方法封裝了異步轉同步的操作,是 future庫中對我們最有價值的方法。 fn表示需要轉換的函數, idx表示 fn接受的參數數目,認為其 callback方法為最后一個參數(這邊API的制定頗有爭議,有人傾向傳遞 callback應該處于的位置,好在 wrap方法比較簡單,可以比較容易修改代碼)??匆粋€例子就能了解 wrap的用法:

復制代碼代碼如下:

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

 

從這個例子中可以看出Fiber異步轉同步確實非常有效,除了語法上多了一步 .wait()外,其他已經 fs提供的 fs.readFileSync方法別無二致了。

4.Future.wait(futures):

這個方法前面已經多次看到了。顧名思義,它的作用就是等待結果。如果要等待一個future的實例的結果,直接調用 futureInstance.wait()即可;如果需要等待一系列future實例的結果,則調用 Future.wait(futuresArray)。需要注意的是,在第二種用法中,一個future實例在運行時出現錯誤, wait方法不會拋出錯誤,不過我們可以使用 get()方法直接獲取運行結果。

5.Future.prototype.get():

get()的用法與 wait()的第一種方式很像,所不同的是, get()立刻返回結果。如果數據沒有準備好, get()會拋出錯誤。

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

上面的的 wrap方法總給人以一種 future其實在吞噬異步方法的回調函數,并直接返回異步結果。事實上 future也通過 resolve方法提供設置回調函數的解決方案。 resolve最多接受兩個參數,如果只傳入一個參數, future認為傳了一個node風格的回調函數,例如如下示例:

復制代碼代碼如下:

futureInstance.resolve(function (err, data) {
    if (err) {
        throw  err;
    } else {
        console.log(data.toString());
    }
});

 

如果傳入兩個參數,則表示對錯誤和數據分別做處理,示例如下:

復制代碼代碼如下:

futureInstance.resolve(function (err) {
    throw err;
}, function (data) {
    console.log(data.toString());
});

 

另外 future并不區分 resolve的調用時機,如果數據沒有準備好,則將回調函數壓入隊列,由 resolver()方法統一調度,否則直接取數據立即執行回調函數。

7.Future.prototype.isResolved():

返回布爾值,表示操作是否已經執行。

8.Future.prototype.proxy(futureInstance):

proxy方法提供一種 future實例的代理,本質上是對 resolve方法的包裝,其實是將一個instance的回調方法作為另一個instance的回調執行者。例如:

 

復制代碼代碼如下:

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(); // 輸出100

 

雖然執行的是 proxy,但是最終 target的回調函數執行了,并且是以 proxy的執行結果驅動 target的回調函數。這種代理手段也許在我們的實際應用中有很大作用,我暫時還沒有深入地思考過。

9.Future.prototype.return(value):

10.Future.prototype.throw(error):

11.Future.prototype.resolver():

12.Future.prototype.detach():

以上四個API呢我感覺相對于別的API,實際使用的場景或作用比較一般。 return和 throw都受 resolver方法調度,這三個方法都很重要,在正常的future使用流程中都會默默工作著,只是我沒有想出具體單獨使用它們的場景,所以沒有辦法具體介紹。 detach方法只能算 resolve方法的簡化版,亦沒有介紹的必要。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表

圖片精選

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲精品之草原avav久久| 91视频国产一区| 77777亚洲午夜久久多人| 亚洲日本成人女熟在线观看| 少妇高潮久久久久久潘金莲| 日韩av不卡在线| 成人精品在线视频| 亚洲精品之草原avav久久| 久久亚洲欧美日韩精品专区| 8090成年在线看片午夜| 精品小视频在线| 国产成人精品av在线| 欧美一级淫片aaaaaaa视频| 97国产一区二区精品久久呦| 国产精品爱久久久久久久| 国产一区香蕉久久| 亚洲一区亚洲二区| 久久久久久久久久国产| 日本不卡高字幕在线2019| 亚洲欧美成人在线| 美女福利精品视频| 国产精品福利无圣光在线一区| 国产精品视频自拍| 日韩免费观看在线观看| 日韩精品免费在线| 亚洲全黄一级网站| 欧美综合国产精品久久丁香| 色老头一区二区三区| 福利精品视频在线| 国产精品劲爆视频| 欧亚精品在线观看| 91九色视频导航| 欧美视频中文在线看| 伊人av综合网| 91精品国产综合久久香蕉| 日韩欧美极品在线观看| 亚洲国产精品视频在线观看| 亚洲人成网站999久久久综合| 国产精品偷伦视频免费观看国产| 国产精品自产拍高潮在线观看| 亚洲精品日韩av| 91久久精品日日躁夜夜躁国产| 中日韩美女免费视频网站在线观看| 日韩av成人在线| 亚洲午夜未满十八勿入免费观看全集| 中文字幕欧美视频在线| 精品视频在线播放色网色视频| 欧美性生交大片免网| 久久精品91久久香蕉加勒比| 中文字幕精品久久久久| 久久精品一区中文字幕| 久久精品国产免费观看| 在线中文字幕日韩| 久久99热精品这里久久精品| 97视频在线观看视频免费视频| 91免费精品国偷自产在线| 日韩有码视频在线| 久久全球大尺度高清视频| 亚洲欧美日韩中文在线| 亚洲国产三级网| 欧美激情手机在线视频| 久久久成人精品| 97精品久久久中文字幕免费| 国产一区视频在线| 欧美一性一乱一交一视频| 久久精品久久久久| 久久免费少妇高潮久久精品99| 51视频国产精品一区二区| 国产精品久久久| 亚洲国产小视频在线观看| 中文字幕国产亚洲2019| 亚洲视频在线观看| 国产精品美女视频网站| 亚洲综合在线小说| 成人激情av在线| 一区二区三区日韩在线| 午夜精品久久17c| 亚洲资源在线看| 亚洲美女动态图120秒| 亚洲欧美日韩视频一区| 欧美日韩爱爱视频| 欧美精品videosex极品1| 777精品视频| 久久在线视频在线| 国产精品久久9| 中文字幕精品www乱入免费视频| 日韩精品视频免费在线观看| www.午夜精品| 国产日韩亚洲欧美| 欧美专区第一页| 国产精品久久婷婷六月丁香| 国产精自产拍久久久久久蜜| 国产91精品在线播放| 欧美大尺度电影在线观看| 亚洲激情成人网| 国产专区精品视频| 久久伊人91精品综合网站| 久久久久久久久久久成人| 久久网福利资源网站| 国产精品第一页在线| 欧美孕妇与黑人孕交| 久久亚洲精品毛片| 91久久久久久久| 日韩小视频在线| 97香蕉久久夜色精品国产| 日韩在线视频免费观看| 日本久久久久亚洲中字幕| 久久国产视频网站| 国产欧美 在线欧美| 亚洲人成欧美中文字幕| 亚洲精品成人久久电影| 亚洲黄色www网站| 按摩亚洲人久久| 国产精品大陆在线观看| 最近2019中文字幕第三页视频| 日韩在线观看网站| 欧美精品久久一区二区| 国产精品久久久久久久久久久不卡| 亚洲另类欧美自拍| 波霸ol色综合久久| 韩国19禁主播vip福利视频| 精品久久久久久久久中文字幕| 久久精品国产免费观看| 国产香蕉97碰碰久久人人| 亚洲人成网站777色婷婷| 国产在线拍揄自揄视频不卡99| 日韩av在线看| 97在线视频精品| 国产成人精品视频在线| 97国产真实伦对白精彩视频8| 欧美精品福利在线| 久久久亚洲影院| 亚洲电影免费观看高清完整版在线观看| 亚洲毛片一区二区| 亚洲精品免费av| 成人伊人精品色xxxx视频| 国产亚洲在线播放| 国产精品美乳一区二区免费| 日本韩国欧美精品大片卡二| 国模精品视频一区二区三区| 91九色国产在线| 一区二区三区久久精品| 国产精品黄页免费高清在线观看| 久久精品国产精品亚洲| 亚洲精品久久久一区二区三区| 亚洲大胆人体av| 日韩亚洲成人av在线| 亚洲全黄一级网站| 国产成人精品综合久久久| 精品美女国产在线| 国产精品扒开腿做| 国产+人+亚洲| 久久视频精品在线| 亚洲成人网在线观看| 欧美日韩精品在线| 黄色91在线观看| 成人激情黄色网| 国产精品第三页| 日韩欧美黄色动漫| 欧美高清视频在线播放| 国产一区二区美女视频| 亚洲97在线观看| 欧美日韩一区二区三区在线免费观看| 亚洲欧美日韩天堂|