欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JS co 函數(shù)庫(kù)的含義和用法實(shí)例總結(jié)

 更新時(shí)間:2020年04月08日 09:41:40   作者:李小強(qiáng)  
這篇文章主要介紹了JS co 函數(shù)庫(kù)的含義和用法,結(jié)合實(shí)例形式總結(jié)分析了JS co 函數(shù)庫(kù)的基本含義、功能、用法及操作注意事項(xiàng),需要的朋友可以參考下

本文實(shí)例講述了JS co 函數(shù)庫(kù)的含義和用法。分享給大家供大家參考,具體如下:

繼續(xù)學(xué)習(xí)阮一峰老師異步編程四部曲之三:co

co在很早之前就聽(tīng)超哥講過(guò),說(shuō)在node編程中大量用到,源碼很簡(jiǎn)單,但是想法很強(qiáng)大。

讓我有空抓緊了解下,前一段時(shí)間弄離職的事情,跑來(lái)跑去累的夠嗆。

現(xiàn)在終于一切回歸正常了,還在拼命的適應(yīng)新公司的節(jié)奏。只能趁周末繼續(xù)學(xué)習(xí)了。

好了,不瞎扯了,回歸主題,前兩篇文章我們分別學(xué)習(xí)了 Generator 函數(shù)和 Thunk 方式的自動(dòng)執(zhí)行。

今天我們接著上次的思路學(xué)習(xí)使用 co 工具實(shí)現(xiàn) Generator 函數(shù)的自動(dòng)執(zhí)行。

再次拿出上一節(jié)的示例:

var fs = require('fs');
var thunkify = require('thunkify');
var readFile = thunkify(fs.readFile);
 
var gen = function* (){
 var r1 = yield readFile('/etc/fstab');
 console.log(r1.toString());
 var r2 = yield readFile('/etc/shells');
 console.log(r2.toString());
};

這段代碼用于讀取兩個(gè)文件,怎么使用 co 工具來(lái)實(shí)現(xiàn)自動(dòng)執(zhí)行呢?

很簡(jiǎn)單:

var co = require('co');
co(gen);

上面代碼中,只要把 Generator 函數(shù)傳入 co 函數(shù),就會(huì)自動(dòng)執(zhí)行。

co 函數(shù)返回一個(gè) Promise 對(duì)象,因此可以用 then 方法添加回調(diào)函數(shù),當(dāng) Generator 執(zhí)行結(jié)束就會(huì)觸發(fā)回調(diào):

co(gen).then(function (){
 //success
});

這么看起來(lái)的話好像和我們之前的 Thunk 方式差不多啊,只是把 run 函數(shù)名改成了 co

唯一的區(qū)別是多了一層 Promise 包裝,那么 co 和 Thunk 到底有什么區(qū)別呢?

正如我們的猜測(cè)一樣,co 其實(shí)是將之前的兩種自動(dòng)執(zhí)行方式(Thunk 和 Promise)結(jié)合到了一起,包裝成一個(gè)庫(kù)。

使用它的前提和比Thunk多了一種 Promise 的情況,也就是yield返回值必須是 Thunk 函數(shù)和 Promise 對(duì)象之一

實(shí)現(xiàn)原理:

之前我們?cè)谘芯?Thunk 函數(shù)時(shí)的第一步是使用 thunkify 將 readFile 包裝成 Thunk 函數(shù):

今天我們研究 Promise 就需要把 readFile 包裝成 Promise 對(duì)象,看代碼:

var fs = require('fs');
 
var readFile = function (fileName){
 return new Promise(function (resolve, reject){
  fs.readFile(fileName, function(error, data){
   if (error) reject(error);
   resolve(data);
  });
 });
};
 
var gen = function* (){
 var f1 = yield readFile('/etc/fstab');
 var f2 = yield readFile('/etc/shells');
 console.log(f1.toString());
 console.log(f2.toString());
};

接下來(lái)是我特別喜歡老師做的一件事,先用最原始的方式,手動(dòng)執(zhí)行一遍代碼。

在我們?nèi)粘i_(kāi)發(fā)的過(guò)程中,也可以參考這種方式。當(dāng)邏輯復(fù)雜時(shí),不妨先用最直白的方式把它實(shí)現(xiàn),

然后再去發(fā)現(xiàn)里面的規(guī)則,去優(yōu)化重構(gòu)。又開(kāi)始扯了,看一下手動(dòng)執(zhí)行的代碼:

var g = gen();
 
g.next().value.then(function(data){
 g.next(data).value.then(function(data){
  g.next(data);
 });
});

手動(dòng)執(zhí)行其實(shí)就是用 then 方法,層層添加回調(diào)函數(shù)。理解了這一點(diǎn),就可以寫(xiě)出一個(gè)自動(dòng)執(zhí)行器:

function run(gen){
 var g = gen();  //開(kāi)始執(zhí)行
 
 function next(data){
  var result = g.next(data);
  if (result.done) return result.value;
  result.value.then(function(data){
   next(data);
  });
 }
 next();
}
run(gen);

和Thunk函數(shù)的區(qū)別是,Thunk 函數(shù)在執(zhí)行成功后把 next 傳給 thunkify ,讓 thunkify 來(lái)幫忙執(zhí)行 next

這里的做法是吧 next 交給 Promise,promise 控制請(qǐng)求成功時(shí)執(zhí)行 next。區(qū)別只有這么一點(diǎn)。

分析了原理之后,我們來(lái)分析下co的源碼:

co 函數(shù)接受一個(gè) Generator 參數(shù),返回一個(gè) Promise 對(duì)象

function co(gen) {
 var ctx = this;
 
 return new Promise(function(resolve, reject) {
 });
}

在返回的 Promise 對(duì)象里面,先檢查參數(shù) gen 是否為 Generator 函數(shù)。如果是,就執(zhí)行該函數(shù),得到一個(gè)內(nèi)部指針對(duì)象;

如果不是就返回,并將 Promise 對(duì)象的狀態(tài)改為 resolved 。

function co(gen) {
 var ctx = this;
 
 return new Promise(function(resolve, reject) {
  if (typeof gen === 'function') gen = gen.call(ctx);
  if (!gen || typeof gen.next !== 'function') return resolve(gen);
 });
}

接著,co 對(duì) next 方法進(jìn)行包裝,使異常能夠暴露出來(lái):

function co(gen) {
 var ctx = this;
 
 return new Promise(function(resolve, reject) {
  if (typeof gen === 'function') gen = gen.call(ctx);
  if (!gen || typeof gen.next !== 'function') return resolve(gen);
 
  onFulfilled();
  function onFulfilled(res) {
   var ret;
   try {
    ret = gen.next(res);
   } catch (e) {
    return reject(e);
   }
   next(ret);
  }  
 });
}

最后就是next方法了:

function next(ret) {
 if (ret.done) return resolve(ret.value);
 var value = toPromise.call(ctx, ret.value);
 if (value && isPromise(value)) return value.then(onFulfilled, onRejected);
 return onRejected(new TypeError('You may only yield a function, promise, generator, array, or object, '
    + 'but the following object was passed: "' + String(ret.value) + '"'));
  }
});

next方法最主要的一行:

if (value && isPromise(value)) return value.then(onFulfilled, onRejected);

co的使用條件,每一次yield返回必須是Promise對(duì)象,當(dāng)promist處理成功時(shí)再次執(zhí)行onFulfilled

以此來(lái)達(dá)到自動(dòng)執(zhí)行的效果。

co 還支持并發(fā)的異步操作,yield 返回一個(gè)數(shù)組或者是支持遍歷的對(duì)象即可:

// 數(shù)組的寫(xiě)法
co(function* () {
 var res = yield [
  Promise.resolve(1),
  Promise.resolve(2)
 ];
 console.log(res); 
}).catch(onerror);
 
// 對(duì)象的寫(xiě)法
co(function* () {
 var res = yield {
  1: Promise.resolve(1),
  2: Promise.resolve(2),
 };
 console.log(res); 
}).catch(onerror);

至此,co 的自動(dòng)執(zhí)行原理我們已經(jīng)學(xué)習(xí)完成了,

其實(shí)本質(zhì)上不是很難,只是涉及到的模塊較多,思路比較靈活

對(duì)我的小容量大腦來(lái)說(shuō),現(xiàn)在的認(rèn)識(shí)還只到90%

所以這篇文章里面自己的思想比較少,更多的還是在復(fù)述老師的思路。

最后貼上原文的地址:co 函數(shù)庫(kù)的含義和用法

感興趣的朋友可以使用在線HTML/CSS/JavaScript代碼運(yùn)行工具http://tools.jb51.net/code/HtmlJsRun測(cè)試上述代碼運(yùn)行效果。

更多關(guān)于JavaScript相關(guān)內(nèi)容可查看本站專(zhuān)題:《JavaScript常用函數(shù)技巧匯總》、《javascript面向?qū)ο笕腴T(mén)教程》、《JavaScript錯(cuò)誤與調(diào)試技巧總結(jié)》、《JavaScript數(shù)據(jù)結(jié)構(gòu)與算法技巧總結(jié)》及《JavaScript數(shù)學(xué)運(yùn)算用法總結(jié)

希望本文所述對(duì)大家JavaScript程序設(shè)計(jì)有所幫助。

相關(guān)文章

  • discuz表情的JS提取方法分析

    discuz表情的JS提取方法分析

    這篇文章主要介紹了discuz表情的JS提取方法,簡(jiǎn)單分析了discuz中表情JS文件調(diào)用的原理與相關(guān)操作技巧,需要的朋友可以參考下
    2017-03-03
  • QRCode.js二維碼生成并能長(zhǎng)按識(shí)別

    QRCode.js二維碼生成并能長(zhǎng)按識(shí)別

    這篇文章主要為大家詳細(xì)介紹了QRCode.js二維碼生成并能長(zhǎng)按識(shí)別,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • 小程序外賣(mài)訂單界面的示例代碼

    小程序外賣(mài)訂單界面的示例代碼

    這篇文章主要介紹了小程序外賣(mài)訂單界面的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • JavaScript引用賦值與傳值賦值總結(jié)

    JavaScript引用賦值與傳值賦值總結(jié)

    這篇文章主要介紹了JavaScript引用賦值與傳值賦值總結(jié),在JavaScript中基本數(shù)據(jù)類(lèi)型都是傳值賦值,復(fù)合數(shù)據(jù)類(lèi)型都是引用賦值(傳地址)也叫引用傳址,下文更多相關(guān)資料,需要的小伙伴可以參考一下
    2022-05-05
  • JavaScript實(shí)現(xiàn)斗地主游戲的思路

    JavaScript實(shí)現(xiàn)斗地主游戲的思路

    這篇文章主要介紹了JavaScript實(shí)現(xiàn)斗地主游戲的思路的相關(guān)資料,需要的朋友可以參考下
    2016-02-02
  • js中關(guān)于promise的用法解讀

    js中關(guān)于promise的用法解讀

    這篇文章主要介紹了js中關(guān)于promise的用法解讀,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • input獲取焦點(diǎn)時(shí)底部菜單被頂上來(lái)問(wèn)題的解決辦法

    input獲取焦點(diǎn)時(shí)底部菜單被頂上來(lái)問(wèn)題的解決辦法

    這篇文章主要介紹了解決input獲取焦點(diǎn)時(shí)底部菜單被頂上來(lái)問(wèn)題的方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的的朋友參考下
    2017-01-01
  • 微信小程序?qū)崿F(xiàn)菜單左右聯(lián)動(dòng)效果

    微信小程序?qū)崿F(xiàn)菜單左右聯(lián)動(dòng)效果

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)菜單左右聯(lián)動(dòng)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • javaScript 利用閉包模擬對(duì)象的私有屬性

    javaScript 利用閉包模擬對(duì)象的私有屬性

    JavaScript缺少塊級(jí)作用域,沒(méi)有private修飾符,但它具有函數(shù)作用域。作用域的好處是內(nèi)部函數(shù)可以訪問(wèn)它們的外部函數(shù)的參數(shù)和變量(除了this和argument
    2011-12-12
  • jQuery實(shí)現(xiàn)為控件添加水印文字效果(附源碼)

    jQuery實(shí)現(xiàn)為控件添加水印文字效果(附源碼)

    這篇文章主要介紹了jQuery實(shí)現(xiàn)為控件添加水印文字效果的方法,涉及jQuery插件jquery.tinywatermark.js的使用技巧,并提供了源碼供讀者下載參考,需要的朋友可以參考下
    2015-12-12

最新評(píng)論