欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

javascript協(xié)程,js 協(xié)程

如何利用Node.js 構(gòu)建分布式集群

那么到底是如何實現(xiàn)服務端調(diào)用解耦的呢?在實現(xiàn)方案中,我們采用了(Node.js + Protocol Buffers + Zookeeper + RabbitMQ)的組合,從而實現(xiàn)配置集中化管理:

創(chuàng)新互聯(lián)公司致力于成都做網(wǎng)站、成都網(wǎng)站設計,成都網(wǎng)站設計,集團網(wǎng)站建設等服務標準化,推過標準化降低中小企業(yè)的建站的成本,并持續(xù)提升建站的定制化服務水平進行質(zhì)量交付,讓企業(yè)網(wǎng)站從市場競爭中脫穎而出。 選擇創(chuàng)新互聯(lián)公司,就選擇了安全、穩(wěn)定、美觀的網(wǎng)站建設服務!

1.Node.js,主要用于開發(fā)業(yè)務邏輯。

作為天生的異步腳本語言,Node.js 使用事件驅(qū)動、 非阻塞I/O模型大大提升了研發(fā)效率,非常適合在分布式設備上運行的數(shù)據(jù)密集型的實時應用。

我們通過 Fibers庫采用協(xié)程的方式來解決Node.js 異步編程匿名回調(diào)問題,將異步回調(diào)邏輯轉(zhuǎn)化為同步,同時也滿足了程序員使用同步方法編寫異步程序的情懷。

可參考官方介紹:

2.Protocol Buffers,用于強約束消息定義。

Protocol Buffers一種數(shù)據(jù)交換的格式,它獨立于語言,獨立于平臺。由于它是一種二進制的格式,相比XML和JSON,傳輸效率會更高,可以將它用于分布式應用之間的數(shù)據(jù)通信或者異構(gòu)環(huán)境下的數(shù)據(jù)交換。我們主要將Protocol Buffers用來模版化定義消息結(jié)構(gòu)。

可參考:

3.Zookeeper,實現(xiàn)配置集中管理。

Zookeeper分布式服務框架是Apache Hadoop 的一個子項目,簡單的說,Zookeeper=文件系統(tǒng)+通知機制。它主要是用來解決分布式應用中經(jīng)常遇到的一些數(shù)據(jù)管理問題,如:統(tǒng)一命名服務、狀態(tài)同步服務、集群管理、分布式應用配置項的管理等。

我們使用ZooKeeper看重的是它不僅支持集群高可用,還支持持久化節(jié)點、臨時節(jié)點存儲和節(jié)點變更監(jiān)控的特點,主要使用了它提供的命名服務、配置管理和集群管理服務。其中,臨時節(jié)點特性用以實現(xiàn)名字服務注冊,節(jié)點變更監(jiān)控實現(xiàn)配置集中管理。

參考:

4.RabbitMQ,實現(xiàn)異構(gòu)通訊服務間的解耦。

Rabbitmq是一種應用程序?qū)贸绦虻耐ㄐ欧椒?,選擇RabbitMQ的原因在于它可以支持集群高可用、簡單易用、性能出色和完善的管理工具(如:Web ui / Rest API )的特點。

使用Rabbitmq中間件服務端實現(xiàn)解耦,其中主要是利用( Work Queue + Topics Exchange )來實現(xiàn)后端的無縫擴容,并采用Publish/Subscribe + RPC 實現(xiàn)調(diào)用解耦,并利用MQ 統(tǒng)一輸入輸出。

參考:

走過的一些坑

最后,總結(jié)經(jīng)驗避免犯同樣的錯,是非常重要的,還有一些技術遺留問題,需要我們自行避開這些坑。以下是我們在構(gòu)建RPC框架過程中遇到的一些坑:

異步編程效率問題(Fibers) Node.js 內(nèi)存泄漏問題

在復雜在構(gòu)建復雜應用的時候,很多地方都可能發(fā)生內(nèi)存泄露,也需要考慮異步編程效率問題。為解決這兩個問題,我們目前主要采取以下三個手段來解決:

a) 框架封裝所有網(wǎng)絡通信,業(yè)務方只關注業(yè)務邏輯、提高研發(fā)效率;

b)通過Fibers 封裝所有異步函數(shù)調(diào)用轉(zhuǎn)換為同步方法;

c)謹慎選擇第三方庫。

異步框架中日志跟蹤

異步程序記錄日志亂序不利于跟蹤業(yè)務邏輯調(diào)用路徑。為解決這個問題,我們通過包裝 Fibers 對每一個 Fiber 實例進行編號,在所有日志輸出中打印 Fiber id 記錄異步調(diào)用路徑,并配合跨模塊會話編號實現(xiàn)請求調(diào)用跟蹤,以此解決日志紀錄的無序問題。

RabbitMQ HA 高可用問題

如果需要實現(xiàn)RabbitMQ HA 高可用特性,有兩種途徑可以實現(xiàn):Server 端 HA 和 Client HA。Server 端的高可用性可使用 LVS 或 HAProxy來實現(xiàn),Client 端的高可用性也是一種選擇,這樣可以減少架構(gòu)復雜度和層次依賴。值得注意的是,實現(xiàn)高可用特性時,要記得開啟Queue 高可用配置。

()

RabbitMQ HA 網(wǎng)絡閃斷導致節(jié)點分區(qū)問題

網(wǎng)絡不穩(wěn)定導致RabbitMQ HA 網(wǎng)絡閃斷,進而導致節(jié)點分區(qū)問題。針對這個問題,需要添加對 /api/nodes 進行監(jiān)控,并及時處理分區(qū)問題。

具體的解決方法可參考:

ZooKeeper Session Expired

針對ZooKeeper 會話過期問題,需要大家特別關注處理Zookeeper 集群斷開后的重連處理,因為如果重連邏輯沒有處理好的話,所有依賴ZooKeeper的特性都將不可用。

具體解決方法可參考:

結(jié) 語

經(jīng)過應用實踐,目前看來 Node.js幾乎可以做到其他后端語言所能做到所有的事情,ES6特性正式發(fā)布如今有人已經(jīng)開始高喊“javascript: The World's Best Programming Language”,但我也并不認為整個后端完全用Node.js來實現(xiàn)會是一個很好的方案。

本文中提到了Node.js的諸多優(yōu)點,如異步、非阻塞和事件驅(qū)動等,但其也存在一些缺點,如默認單進程單線程不能利用多核,腳本弱類型容易出現(xiàn)運行時BUG,同時因為它簡單易用,也導致了代碼質(zhì)量不易控制,對開發(fā)人員也提出了更高的要求。所以,就個人經(jīng)驗來看,建議偏復雜業(yè)務邏輯控制使用Node.js,如果是偏極致性能的業(yè)務建議和C++等其他方案結(jié)合使用。

c#coroutine怎么實現(xiàn)

在C#中直接有Thread這個線程,但是在unity中有些元素是不能操作的。這個時候可以使用協(xié)程來完成。

使用線程的好處就是不會出現(xiàn)界面卡死的情況,如果有一次非常大量的運算,沒用線程就會出現(xiàn)假死的情況。

下面通過一個簡單的例子來說明使用協(xié)程的好處:

void OnGUI()

{

GUI.Label(new Rect(0, 0, 200, 50), "測試1:" + result);

if (GUI.Button(new Rect(0, 100, 100, 50), "開啟協(xié)程"))

{

StartCoroutine(GetResult());

}

GUI.Label(new Rect(200, 0, 200, 50), "測試2:" + result1);

if (GUI.Button(new Rect(200, 100, 100, 50), "無協(xié)程測試"))

{

GetResult1();

}

}

上面的代碼表示在GUI中定義2個label和按鈕,一個按鈕啟動協(xié)程計算,另一個直接計算結(jié)果。由于2個方法都是計算同樣的結(jié)果,計算量比較大,所以直接計算出現(xiàn)了暫時的卡死情況。

float result;

IEnumerator GetResult()

{

for (int i = 0; i 1000; i++)

{

for (int j = 0; j 100000; j++)

{

result += (i + j);

}

if(i%100==0)

yield return 1;

}

}

這個方法是協(xié)程的寫法,在C#中協(xié)程要定義為IEnumerator 這個類型,javascript中不需要。

yield return 1;這句話表示返回1幀的結(jié)果。在i為100的整數(shù)時,就返回一次結(jié)果,這樣可以避免大量的計算卡死。

float result1;

void GetResult1()

{

for (int i = 0; i 1000; i++)

{

for (int j = 0; j 100000; j++)

{

result1 += (i + j);

}

}

}

這個方法就是直接計算結(jié)果,由于運算量比較大,所以界面會卡死,這樣就可以體現(xiàn)出用協(xié)程的好處了。

使用IEnumerator 這個類型時,必須用yield return來返回結(jié)果,參數(shù)為數(shù)字時表示為幀數(shù)。

如yield return 1 表示每一幀返回一次結(jié)果。

可以幫我翻譯一下這段英文嗎(關于協(xié)程的描述)

該executation的coroutine可以在任何時候暫停使用產(chǎn)量發(fā)言。產(chǎn)量返回值指定當coroutine復會。 Coroutines良好行為時,模擬多個幀。 Coroutines幾乎沒有任何的性能開銷。 StartCoroutine功能總是立即返回,但是,您可以產(chǎn)生的結(jié)果。這將等到couroutine已完成執(zhí)行。

當使用JavaScript ,沒有必要使用StartCoroutine ,編譯器會幫您進行此動作。寫作時C #代碼,你必須撥打StartCoroutine

/ /在這個例子中,我們顯示了如何調(diào)用一個coroutine ,并繼續(xù)執(zhí)行

/ /函數(shù)并行。

/ / -在0秒,打印“從0.0 ”

/ / -在0秒,打印“在WaitAndPrint油劑0.0 ”

/ / - 2秒鐘后,打印“ WaitAndPrint 2.0 ”

打?。?“啟動” + Time.time ) ;

/ /啟動功能WaitAndPrint作為coroutine 。并等待,直到它完成

WaitAndPrint ( 2.0 ) ;

打印( “在WaitAndPrint油劑” + Time.time ) ;

功能WaitAndPrint ( waitTime為: float ) (

/ /停止執(zhí)行的waitTime秒

產(chǎn)量WaitForSeconds ( waitTime ) ;

打?。?“ WaitAndPrint ” + Time.time ) ;

功能StartCoroutine ( methodName :字符串,值:對象=無效) : Coroutine

描述

啟動一個coroutine名為methodName 。

在大多數(shù)情況下要使用上述StartCoroutine變化。然而StartCoroutine方法使用一個字符串名稱,您就可以使用StopCoroutine具體方法的名稱。缺點是,字符串版本具有更高的運行時開銷開始coroutine ,您可以通過唯一的一個參數(shù)

fiber javascript 可以做什么

1, 用 fiber 還是等語法層面的改進,我認為是見仁見智。我不認為讓開發(fā)者關心一個調(diào)用是同步還是異步是一件好事情。

我在微博上面說過,異步是會向上傳染的,語言級的協(xié)程無法根本解決異步問題。在一個層級較深的項目里面,一旦底層中有一個模塊需要同步改異步或者相反(比如需要增加一次數(shù)據(jù)庫操作),向上的每一個層級都需要在語法上進行修改,這一點是災難的。我不認為 js 能最終解決這個問題,最后必須回歸堆棧級協(xié)程。

2, 從純 js 性能來說,fiber 比 callback 要高出非常多。fibjs 的模塊之間是最簡單的函數(shù)調(diào)用關系,而 callback 則需要往返兩次才能完成一次調(diào)用,期間還要結(jié)果組包,錯誤處理,保存工作狀態(tài)等等耗時操作。同時 nodejs 的事件隊列也是一個性能堪憂的東西。越復雜的應用,這些影響越大。

數(shù)據(jù)庫操作,沒有做詳細對比測試。封裝 leveldb 的時候簡單測試了一下,fibjs 9w/s,nodejs 3w/s。http + mongodb 有網(wǎng)友測試結(jié)果在這里:,基本也是將近 3 倍。并且這些測試里面,fibjs 的瓶頸根本不在 fibjs 而 nodejs 則是已經(jīng)跑滿了。

javascript中異步操作的異常怎么處理

一、JavaScript異步編程的兩個核心難點

異步I/O、事件驅(qū)動使得單線程的JavaScript得以在不阻塞UI的情況下執(zhí)行網(wǎng)絡、文件訪問功能,且使之在后端實現(xiàn)了較高的性能。然而異步風格也引來了一些麻煩,其中比較核心的問題是:

1、函數(shù)嵌套過深

JavaScript的異步調(diào)用基于回調(diào)函數(shù),當多個異步事務多級依賴時,回調(diào)函數(shù)會形成多級的嵌套,代碼變成

金字塔型結(jié)構(gòu)。這不僅使得代碼變難看難懂,更使得調(diào)試、重構(gòu)的過程充滿風險。

2、異常處理

回調(diào)嵌套不僅僅是使代碼變得雜亂,也使得錯誤處理更復雜。這里主要講講異常處理。

二、異常處理

像很多時髦的語言一樣,JavaScript 也允許拋出異常,隨后再用一個try/catch

語句塊捕獲。如果拋出的異常未被捕獲,大多數(shù)JavaScript環(huán)境都會提供一個有用的堆棧軌跡。舉個例子,下面這段代碼由于'{'為無效JSON

對象而拋出異常。

?

12345678

function JSONToObject(jsonStr) { return JSON.parse(jsonStr);}var obj = JSONToObject('{');//SyntaxError: Unexpected end of input//at Object.parse (native)//at JSONToObject (/AsyncJS/stackTrace.js:2:15)//at Object.anonymous (/AsyncJS/stackTrace.js:4:11)

堆棧軌跡不僅告訴我們哪里拋出了錯誤,而且說明了最初出錯的地方:第4 行代碼。遺憾的是,自頂向下地跟蹤異步錯誤起源并不都這么直截了當。

異步編程中可能拋出錯誤的情況有兩種:回調(diào)函數(shù)錯誤、異步函數(shù)錯誤。

1、回調(diào)函數(shù)錯誤

如果從異步回調(diào)中拋出錯誤,會發(fā)生什么事?讓我們先來做個測試。

?

1234567

setTimeout(function A() { setTimeout(function B() { setTimeout(function C() { throw new Error('Something terrible has happened!'); }, 0); }, 0);}, 0);

上述應用的結(jié)果是一條極其簡短的堆棧軌跡。

?

12

Error: Something terrible has happened!at Timer.C (/AsyncJS/nestedErrors.js:4:13)

等等,A 和B 發(fā)生了什么事?為什么它們沒有出現(xiàn)在堆棧軌跡中?這是因為運行C 的時候,異步函數(shù)的上下文已經(jīng)不存在了,A 和B 并不在內(nèi)存堆棧里。這3

個函數(shù)都是從事件隊列直接運行的。基于同樣的理由,利用try/catch

語句塊并不能捕獲從異步回調(diào)中拋出的錯誤。另外回調(diào)函數(shù)中的return也失去了意義。

?

1234567

try { setTimeout(function() { throw new Error('Catch me if you can!'); }, 0);} catch (e) {console.error(e);}

看到這里的問題了嗎?這里的try/catch 語句塊只捕獲setTimeout函數(shù)自身內(nèi)部發(fā)生的那些錯誤。因為setTimeout

異步地運行其回調(diào),所以即使延時設置為0,回調(diào)拋出的錯誤也會直接流向應用程序。

總的來說,取用異步回調(diào)的函數(shù)即使包裝上try/catch 語句塊,也只是無用之舉。(特例是,該異步函數(shù)確實是在同步地做某些事且容易出錯。例如,Node

的fs.watch(file,callback)就是這樣一個函數(shù),它在目標文件不存在時會拋出一個錯誤。)正因為此,Node.js

中的回調(diào)幾乎總是接受一個錯誤作為其首個參數(shù),這樣就允許回調(diào)自己來決定如何處理這個錯誤。

2、異步函數(shù)錯誤

由于異步函數(shù)是立刻返回的,異步事務中發(fā)生的錯誤是無法通過try-catch來捕捉的,只能采用由調(diào)用方提供錯誤處理回調(diào)的方案來解決。

例如Node中常見的function (err, ...)

{...}回調(diào)函數(shù),就是Node中處理錯誤的約定:即將錯誤作為回調(diào)函數(shù)的第一個實參返回。再比如HTML5中FileReader對象的onerror函數(shù),會被用于處理異步讀取文件過程中的錯誤。

舉個例子,下面這個Node 應用嘗試異步地讀取一個文件,還負責記錄下任何錯誤(如“文件不存在”)。

?

1234567

var fs = require('fs'); fs.readFile('fhgwgdz.txt', function(err, data) { if (err) { return console.error(err); }; console.log(data.toString('utf8'));});

客戶端JavaScript 庫的一致性要稍微差些,不過最常見的模式是,針對成敗這兩種情形各規(guī)定一個單獨的回調(diào)。jQuery 的Ajax

方法就遵循了這個模式。

?

1234

$.get('/data', { success: successHandler, failure: failureHandler});

不管API 形態(tài)像什么,始終要記住的是,只能在回調(diào)內(nèi)部處理源于回調(diào)的異步錯誤。

三、未捕獲異常的處理

如果是從回調(diào)中拋出異常的,則由那個調(diào)用了回調(diào)的人負責捕獲該異常。但如果異常從未被捕獲,又會怎么樣?這時,不同的JavaScript環(huán)境有著不同的游戲規(guī)則……

1. 在瀏覽器環(huán)境中

現(xiàn)代瀏覽器會在開發(fā)人員控制臺顯示那些未捕獲的異常,接著返回事件隊列。要想修改這種行為,可以給window.onerror

附加一個處理器。如果windows.onerror 處理器返回true,則能阻止瀏覽器的默認錯誤處理行為。

?

123

window.onerror = function(err) { return true; //徹底忽略所有錯誤};

在成品應用中, 會考慮某種JavaScript 錯誤處理服務, 譬如Errorception。Errorception

提供了一個現(xiàn)成的windows.onerror 處理器,它向應用服務器報告所有未捕獲的異常,接著應用服務器發(fā)送消息通知我們。

2. 在Node.js 環(huán)境中

在Node 環(huán)境中,window.onerror 的類似物就是process 對象的uncaughtException 事件。正常情況下,Node

應用會因未捕獲的異常而立即退出。但只要至少還有一個uncaughtException 事件處理

器,Node 應用就會直接返回事件隊列。

?

123

process.on('uncaughtException', function(err) { console.error(err); //避免了關停的命運!});

但是,自Node 0.8.4 起,uncaughtException 事件就被廢棄了。據(jù)其文檔所言,對異常處理而言,uncaughtException

是一種非常粗暴的機制,請勿使用uncaughtException,而應使用Domain 對象。

Domain 對象又是什么?你可能會這樣問。Domain 對象是事件化對象,它將throw 轉(zhuǎn)化為'error'事件。下面是一個例子。

?

123456789

var myDomain = require('domain').create();myDomain.run(function() { setTimeout(function() { throw new Error('Listen to me!') }, 50);});myDomain.on('error', function(err) { console.log('Error ignored!');});

源于延時事件的throw 只是簡單地觸發(fā)了Domain 對象的錯誤處理器。

Error ignored!

很奇妙,是不是?Domain 對象讓throw

語句生動了很多。不管在瀏覽器端還是服務器端,全局的異常處理器都應被視作最后一根救命稻草。請僅在調(diào)試時才使用它。

四、幾種解決方案

下面對幾種解決方案的討論主要集中于上面提到的兩個核心問題上,當然也會考慮其他方面的因素來評判其優(yōu)缺點。

1、Async.js

首先是Node中非常著名的Async.js,這個庫能夠在Node中展露頭角,恐怕也得歸功于Node統(tǒng)一的錯誤處理約定。

而在前端,一開始并沒有形成這么統(tǒng)一的約定,因此使用Async.js的話可能需要對現(xiàn)有的庫進行封裝。

Async.js的其實就是給回調(diào)函數(shù)的幾種常見使用模式加了一層包裝。比如我們需要三個前后依賴的異步操作,采用純回調(diào)函數(shù)寫法如下:

?

12345678910111213141516

asyncOpA(a, b, (err, result) = { if (err) { handleErrorA(err); } asyncOpB(c, result, (err, result) = { if (err) { handleErrorB(err); } asyncOpB(d, result, (err, result) = { if (err) { handlerErrorC(err); } finalOp(result); }); });});

如果我們采用async庫來做:

?

12345678910111213141516171819202122

async.waterfall([ (cb) = { asyncOpA(a, b, (err, result) = { cb(err, c, result); }); }, (c, lastResult, cb) = { asyncOpB(c, lastResult, (err, result) = { cb(err, d, result); }) }, (d, lastResult, cb) = { asyncOpC(d, lastResult, (err, result) = { cb(err, result); }); }], (err, finalResult) = { if (err) { handlerError(err); } finalOp(finalResult);});

可以看到,回調(diào)函數(shù)由原來的橫向發(fā)展轉(zhuǎn)變?yōu)榭v向發(fā)展,同時錯誤被統(tǒng)一傳遞到最后的處理函數(shù)中。

其原理是,將函數(shù)數(shù)組中的后一個函數(shù)包裝后作為前一個函數(shù)的末參數(shù)cb傳入,同時要求:

每一個函數(shù)都應當執(zhí)行其cb參數(shù);cb的第一個參數(shù)用來傳遞錯誤。我們可以自己寫一個async.waterfall的實現(xiàn):

?

12345678910111213141516171819202122

let async = { waterfall: (methods, finalCb = _emptyFunction) = { if (!_isArray(methods)) { return finalCb(new Error('First argument to waterfall must be an array of functions')); } if (!methods.length) { return finalCb(); } function wrap(n) { if (n === methods.length) { return finalCb; } return function (err, ...args) { if (err) { return finalCb(err); } methods[n](...args, wrap(n + 1)); } } wrap(0)(false); }};

Async.js還有series/parallel/whilst等多種流程控制方法,來實現(xiàn)常見的異步協(xié)作。

Async.js的問題:

在外在上依然沒有擺脫回調(diào)函數(shù),只是將其從橫向發(fā)展變?yōu)榭v向,還是需要程序員熟練異步回調(diào)風格。

錯誤處理上仍然沒有利用上try-catch和throw,依賴于“回調(diào)函數(shù)的第一個參數(shù)用來傳遞錯誤”這樣的一個約定。

2、Promise方案

ES6的Promise來源于Promise/A+。使用Promise來進行異步流程控制,有幾個需要注意的問題,

把前面提到的功能用Promise來實現(xiàn),需要先包裝異步函數(shù),使之能返回一個Promise:

?

12345678910

function toPromiseStyle(fn) { return (...args) = { return new Promise((resolve, reject) = { fn(...args, (err, result) = { if (err) reject(err); resolve(result); }) }); };}

這個函數(shù)可以把符合下述規(guī)則的異步函數(shù)轉(zhuǎn)換為返回Promise的函數(shù):

回調(diào)函數(shù)的第一個參數(shù)用于傳遞錯誤,第二個參數(shù)用于傳遞正常的結(jié)果。接著就可以進行操作了:

?

123456789101112131415

let [opA, opB, opC] = [asyncOpA, asyncOpB, asyncOpC].map((fn) = toPromiseStyle(fn)); opA(a, b) .then((res) = { return opB(c, res); }) .then((res) = { return opC(d, res); }) .then((res) = { return finalOp(res); }) .catch((err) = { handleError(err); });

通過Promise,原來明顯的異步回調(diào)函數(shù)風格顯得更像同步編程風格,我們只需要使用then方法將結(jié)果傳遞下去即可,同時return也有了相應的意義:

在每一個then的onFullfilled函數(shù)(以及onRejected)里的return,都會為下一個then的onFullfilled函數(shù)(以及onRejected)的參數(shù)設定好值。

如此一來,return、try-catch/throw都可以使用了,但catch是以方法的形式出現(xiàn),還是不盡如人意。

3、Generator方案

ES6引入的Generator可以理解為可在運行中轉(zhuǎn)移控制權給其他代碼,并在需要的時候返回繼續(xù)執(zhí)行的函數(shù)。利用Generator可以實現(xiàn)協(xié)程的功能。

將Generator與Promise結(jié)合,可以進一步將異步代碼轉(zhuǎn)化為同步風格:

?

1234567891011

function* getResult() { let res, a, b, c, d; try { res = yield opA(a, b); res = yield opB(c, res); res = yield opC(d); return res; } catch (err) { return handleError(err); }}

然而我們還需要一個可以自動運行Generator的函數(shù):

?

123456789101112131415161718192021222324252627282930

function spawn(genF, ...args) { return new Promise((resolve, reject) = { let gen = genF(...args); function next(fn) { try { let r = fn(); if (r.done) { resolve(r.value); } Promise.resolve(r.value) .then((v) = { next(() = { return gen.next(v); }); }).catch((err) = { next(() = { return gen.throw(err); }) }); } catch (err) { reject(err); } } next(() = { return gen.next(undefined); }); });}

用這個函數(shù)來調(diào)用Generator即可:

?

1234567

spawn(getResult) .then((res) = { finalOp(res); }) .catch((err) = { handleFinalOpError(err); });

可見try-catch和return實際上已經(jīng)以其原本面貌回到了代碼中,在代碼形式上也已經(jīng)看不到異步風格的痕跡。

類似的功能有co/task.js等庫實現(xiàn)。

4、ES7的async/await

ES7中將會引入async function和await關鍵字,利用這個功能,我們可以輕松寫出同步風格的代碼,

同時依然可以利用原有的異步I/O機制。

采用async function,我們可以將之前的代碼寫成這樣:

?

12345678910111213

async function getResult() { let res, a, b, c, d; try { res = await opA(a, b); res = await opB(c, res); res = await opC(d); return res; } catch (err) { return handleError(err); }} getResult();

和Generator Promise方案看起來沒有太大區(qū)別,只是關鍵字換了換。

實際上async

function就是對Generator方案的一個官方認可,將之作為語言內(nèi)置功能。

async function的缺點:

await只能在async function內(nèi)部使用,因此一旦你寫了幾個async function,或者使用了依賴于async

function的庫,那你很可能會需要更多的async function。

目前處于提案階段的async

function還沒有得到任何瀏覽器或Node.JS/io.js的支持。Babel轉(zhuǎn)碼器也需要打開實驗選項,并且對于不支持Generator的瀏覽器來說,還需要引進一層厚厚的regenerator

runtime,想在前端生產(chǎn)環(huán)境得到應用還需要時間。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助。

本文題目:javascript協(xié)程,js 協(xié)程
本文URL:http://chinadenli.net/article0/dsdegio.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、微信小程序營銷型網(wǎng)站建設、網(wǎng)站策劃網(wǎng)站改版、關鍵詞優(yōu)化

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都seo排名網(wǎng)站優(yōu)化