国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

js異步解決方案 --- 回調(diào)函數(shù) vs promise vs generater/yield vs

0xE7A38A / 2033人閱讀

摘要:異步流程管理說白了就是為了解決回調(diào)地獄的問題。對象代表一個異步操作,有三種狀態(tài)進行中已成功和已失敗。如果改變已經(jīng)發(fā)生了,你再對對象添加回調(diào)函數(shù),也會立即得到這個結果。執(zhí)行函數(shù)后返回的是一個遍歷器對象,可以依次遍歷函數(shù)內(nèi)部的每一個狀態(tài)。

javascript -- 深度解析異步解決方案
高級語言層出不窮, 然而唯 js 鶴立雞群, 這要說道js的設計理念, js天生為異步而生, 正如布道者樸靈在 node深入淺出--(有興趣的可以讀一下, 很有意思^_^) , 異步很早就存在于操作系統(tǒng)的底層, 意外的是,在絕大多數(shù)高級編程語言中,異步并不多見,疑似被屏蔽了一搬. 造成這個現(xiàn)象的原因或許令人驚訝, 程序員不太適合通過異步來實現(xiàn)進行程序設計 ^_^.

異步的理念是很好的, 然而在程序員編程過程中確實會出現(xiàn)一些問題, 并不是這種理念不容以讓人接受, 而是當有大量的異步操作時會讓你的代碼可讀性降低, 其中回調(diào)函數(shù)異步編程容易產(chǎn)生毀掉陷阱, 即 callback hell--(不要急, 后面會詳細講解)

然而 js 社區(qū)從為停止其腳步, 最新的 ES7 所推出的 async/await 終極異步解決方案, 說終極可能有所不嚴禁, 然而它確實已經(jīng)完全將原來通過模塊侵入式的異步編程解脫出來, 可以讓程序員以接近傳統(tǒng)意義上的函數(shù)調(diào)用實現(xiàn)異步編程, 這是 js 里程碑式變革中極其重要的一部分.

Javascript異步編程解決方案歷史與方法

ES 6以前:

回調(diào)函數(shù)
回調(diào)函數(shù)是最原始的異步編程方案, 上篇文章已經(jīng)講述, 這里不再累贅, 這里給出傳送門 回調(diào)函數(shù)之美 然而如果業(yè)務邏輯過多時, 回調(diào)函數(shù)會產(chǎn)生深層嵌套, 對程序員極不友好,
如下代碼所示有一個業(yè)務邏輯, 需要對a, b, c三個文件一次讀取

    var fs = require("fs");
    
    fs.readFile("./a.txt", function(err1, data1) {
         fs.readFile("./b.txt", function(err2, data2) {
              fs.writeFile("./ab.txt", data1 + data2, function(err) {
                   console.log("read and write done!");
              });
         });
    });

三個異步函數(shù)嵌套看起來挺簡單的, 這里知識簡單假設, 拋磚引玉, 如果有5個,10個甚至更多的異步函數(shù)要順序執(zhí)行,那要嵌套(大家都不喜歡身材橫著長吧哈哈)說實話相當恐怖,代碼會變得異常難讀,難調(diào)試,難維護。這就是所謂的回調(diào)地獄或者callback hell。正是為了解決這個問題,才有了后面兩節(jié)要講的內(nèi)容,用promise或generator進行異步流程管理。異步流程管理說白了就是為了解決回調(diào)地獄的問題。所以說任何事情都有兩面性,異步編程有它獨特的優(yōu)勢,卻也同時遇到了同步編程根本不會有的代碼組織難題。

事件監(jiān)聽(事件發(fā)布/訂閱)
事件監(jiān)聽模式是一種廣泛應用于異步編程的模式, 是回調(diào)函數(shù)的事件化,即發(fā)布/訂閱模式,

    var util = require("util");
    var events = require("events");
    
    function Stream() {
      events.EventEmitter.call(this);
    }
    util.inherits(Stream, events.EventEmitter)
    let got = new Stream();
    got.on("done", function (params) {
      console.log(params);
    });
    got.on("done", function (params) {
      console.log("QWER");
    });
    got.emit("done", "diyige");
    console.log("-----------------");
    
    var emitter = new events.EventEmitter();
    
    emitter.on("done", function (params) {
      console.log(params);
    });
    emitter.on("done", function (params) {
      console.log("ZXCV");
    });
    emitter.emit("done", "dierge");
    
    // diyige
    // QWER
    // dierge
    // ZXCV

Promise對象
Promise 是異步編程的一種解決方案,它是比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大, 它的目的是替換以前回調(diào)函數(shù)的比不編程方案, 也是后續(xù)介紹的異步解決方案的基礎, 它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象, 現(xiàn)在的 js庫幾乎都支持這種異步方案

promise對象有以下特點

對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作,有三種狀態(tài):pending(進行中)、fulfilled(已成功)和rejected(已失敗)。只有異步操作的結果,可以決定當前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。這也是Promise這個名字的由來,它的英語意思就是“承諾”,表示其他手段無法改變

一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結果。Promise對象的狀態(tài)改變,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結果,這時就稱為 resolved(已定型)。如果改變已經(jīng)發(fā)生了,你再對Promise對象添加回調(diào)函數(shù),也會立即得到這個結果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監(jiān)聽,是得不到結果的。

下面為單個promise對象應用方法
    var promise = new Promise(function(resolve,reject){
      // ... some code
      if(/* 異步操作成功 */){
        resolve(value);
      }else{
        reject(error);
      }
    });

通常用promise 的時候我們一般把它相應的業(yè)務包裝起來下圖所示模擬了一個讀取文件的異步
promise 函數(shù),

    var readFile =  function (params) {
      return new Promise(function(resolve, reject){
    
        setTimeout(function(){
            resolve(params);
        }, 2000);
      });
    }
    
    readFile("file1").then(function (data) {
      console.log(data);
      return readFile("file2")
    }).then(function (data) {
      console.log(data);
      return readFile("file3")
    }).then(function (data) {
      console.log(data);
      return readFile("file4")
    }).then(function (data) {
      console.log(data);
      return readFile("file5")
    }).then(function (data) {
      console.log(data);
    })
    //file1
    //file2
    //file3
    //file4
    //file5

流程控制庫
還有一種需要手工調(diào)用采能夠處理后續(xù)任務的, 在這里只簡單介紹一種, 我們稱之為尾觸發(fā), 常用的關鍵字為 next , 為什么要講到它是因為它是 node 神級框架 express中采用的模式, 這里可能要涉及一些后端node的內(nèi)容
在 node 搭建服務器時需要面向 切面編程 ,這就需要各種各樣的中間件

    var app = connect();
    // Middleware
    app.use(connect.staticCache());
    app.use(connect.static(__dirname + "/public"));
    app.use(connect.cookieParser());
    app.use(connect.session());
    app.use(connect.query());
    app.use(connect.bodyParser());
    app.use(connect.csrf());
    app.listen(3001);

在通過 use() 方法監(jiān)聽好一系列中間件后, 監(jiān)聽端口上的請求, 中間件采用的是尾觸發(fā)的機制, 下面是個一個簡單的中間件

    function (req, res, next) {
    // express中間件
    }

每個中間件傳遞請求對象, 響應對象, 和尾觸發(fā)函數(shù), 通過隊列形成一個處理流, 如下圖

中間件機制使得在處理網(wǎng)絡請求時, 可以像面向切面編程一樣進行過濾, 驗證, 日志等功能.

ES 6:

Generator函數(shù)(協(xié)程coroutine)
Generator 函數(shù)有多種理解角度。語法上,Generator 函數(shù)是一個狀態(tài)機,封裝了多個內(nèi)部狀態(tài)。
執(zhí)行 Generator 函數(shù)會返回一個遍歷器對象,也就是說,Generator 函數(shù)除了狀態(tài)機,還是一個遍歷器對象生成函數(shù)。執(zhí)行函數(shù)后返回的是一個遍歷器對象,可以依次遍歷 Generator 函數(shù)內(nèi)部的每一個狀態(tài)。

    function* helloWorldGenerator() {
          yield "hello";
          yield "world";
          return "ending";
    }
    var hw = helloWorldGenerator();
    hw.next()
    // { value: "hello", done: false }
    
    hw.next()
    // { value: "world", done: false }
    
    hw.next()
    // { value: "ending", done: true }
    
    hw.next()
    // { value: undefined, done: true }

下一步,必須調(diào)用遍歷器對象的next方法,使得指針移向下一個狀態(tài)。也就是說,每次調(diào)用next方法,內(nèi)部指針就從函數(shù)頭部或上一次停下來的地方開始執(zhí)行,直到遇到下一個yield表達式(或return語句)為止。換言之,Generator 函數(shù)是分段執(zhí)行的,yield表達式是暫停執(zhí)行的標記,而next方法可以恢復執(zhí)行。

基于 Promise 對象的自動執(zhí)行
generater/yield函數(shù)還無法真正解決異步方案的問題, 需要配合額外的執(zhí)行模塊 如 TJ Holowaychuk 的 co 模塊, 在這里用promise模塊進行generater函數(shù)的自動執(zhí)行;

    var fs = require("fs");
    
    var readFile = function (fileName){
      return new Promise(function (resolve, reject){
        fs.readFile(fileName, function(error, data){
          if (error) return 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());
    };
/*****************************************
       
        var g = gen();
        g.next().value.then(function(data){
          g.next(data).value.then(function(data){
            g.next(data);
          });
        });
*****************************************/
    // 自動執(zhí)行函數(shù)        
    function run(gen){
      var g = gen();
    
      function next(data){
        var result = g.next(data);
        if (result.done) return result.value;
        result.value.then(function(data){
          next(data);
        });
      }
    
      next();
    }
    run(gen);   

ES 7:

async/await
終于來到了我們夢寐以求的的"終極"異步解決方案, 或許你有些失望, 當然這種失望是async/await 僅僅是語法糖, async/await 就是 generater/yield/promise + 自動執(zhí)行模塊的封裝.相對于前輩 async 函數(shù)可以自動執(zhí)行 并且 await 關鍵字后面則只能帶promise隊形--這里注意 await 后面支持其他數(shù)據(jù)類型, 但是底層也會將其轉化為promise對象

async函數(shù)對 Generator 函數(shù)的改進,體現(xiàn)在以下四點。

內(nèi)置執(zhí)行器。
Generator 函數(shù)的執(zhí)行必須靠執(zhí)行器,所以才有了co模塊,而async函數(shù)自帶執(zhí)行器,這完全不像 Generator 函數(shù),需要調(diào)用next方法,或者用co模塊,才能真正執(zhí)行,得到最后結果。

更好的語義。
async和await,比起星號和yield,語義更清楚了。async表示函數(shù)里有異步操作,await表示緊跟在后面的表達式需要等待結果。

更廣的適用性。
co模塊約定,yield命令后面只能是 Thunk 函數(shù)或 Promise 對象,而async函數(shù)的await命令后面,可以是 Promise 對象和原始類型的值(數(shù)值、字符串和布爾值,但這時等同于同步操作)

返回值是 Promise。
async函數(shù)的返回值是 Promise 對象,這比 Generator 函數(shù)的返回值是 Iterator 對象方便多了。你可以用then方法指定下一步的操作。進一步說,async函數(shù)完全可以看作多個異步操作,包裝成的一個 Promise 對象,而await命令就是內(nèi)部then命令的語法糖。

    function name(params) {
      return new Promise(function (resolve, reject) {
        setTimeout(() => {
          resolve(params)
        }, 3000);
      });
    }
    async function myf () {
      let gf = await name("xiaohua");
      let gf2 = await name("xiaohong");
      return gf + gf2 
    }
    async function myf3 (params) {
      let aaa = await myf();
      return aaa;
    }
    myf3().then(function (params) {
      console.log(params);
    });
    
    // xiaohuaxiaohong

async/await 對前者的generater/yield 進行了高度的封裝配合那些支持 promise 實現(xiàn)的庫可以完美的像普通函數(shù)一樣調(diào)用, 并且async函數(shù)與其他async函數(shù)也可以完美無縫連接, 堪稱終極方案

koa2已經(jīng)支持 async/await 但是最新的 express框架依然沒有支持這種寫法, async/await 是大勢所趨, 或許不久的將來 express也會支持它, 我們拭目以待

文章版權歸作者所有,未經(jīng)允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/107112.html

相關文章

  • Nodejs高性能原理(下) --- 事件循環(huán)詳解

    摘要:如果一個即時定時器是被一個正在執(zhí)行的回調(diào)排入隊列的,則該定時器直到下一次事件循環(huán)迭代才會被觸發(fā)。參數(shù)描述在事件循環(huán)的當前回合結束時要調(diào)用的函數(shù)。事件輪詢隨后的調(diào)用,會在任何事件包括定時器之前運行。 系列文章 Nodejs高性能原理(上) --- 異步非阻塞事件驅動模型Nodejs高性能原理(下) --- 事件循環(huán)詳解 前言 終于開始我nodejs的博客生涯了,先從基本的原理講起.以前寫...

    newsning 評論0 收藏0
  • RxJS Observables vs Promise 之簡單對比

    摘要:最近在學習,它是使用的響應式編程的庫,它使編寫異步或基于回調(diào)的代碼更容易。返回的是一個對于指定的。發(fā)送請求使用了,雖然了多次,但是僅發(fā)送一次請求,了結果。中有一些操作符可以讓監(jiān)聽強制為異步的方式,例如。最近在學習RxJS,它是使用 Observables 的響應式編程的庫,它使編寫異步或基于回調(diào)的代碼更容易。 下面主要介紹Observables 與 promise的不同點。 單值與多值 c...

    klivitamJ 評論0 收藏0
  • JavaScript 的 4 種數(shù)組遍歷方法: for VS forEach() VS for/in

    摘要:對于,除非使用箭頭函數(shù),它的回調(diào)函數(shù)的將會變化。使用測試下面的代碼,結果如下打印打印要點使用的規(guī)則要求所有回調(diào)函數(shù)必須使用箭頭函數(shù)。 譯者按: JS 騷操作。 原文:For vs forEach() vs for/in vs for/of in JavaScript 譯者: Fundebug 本文采用意譯,版權歸原作者所有 我們有多種方法來遍歷 JavaScript 的數(shù)組或者...

    joyqi 評論0 收藏0
  • $.ajax vs axios vs fetch

    摘要:使用它可以讓頁面請求少量的數(shù)據(jù),而不用刷新整個頁面。這是一個比較粗糙的,不符合關注分離的設計原則,配置和使用都不是那么友好。它的一個優(yōu)勢異步操作,但的異步操作是基于事件的異步模型,沒有那么友好。 Ajax 是什么? 答:Ajax是一種可以在瀏覽器和服務器之間使用異步數(shù)據(jù)傳輸(HTTP請求)的技術。使用它可以讓頁面請求少量的數(shù)據(jù),而不用刷新整個頁面。而傳統(tǒng)的頁面(不使用Ajax)要刷新...

    bitkylin 評論0 收藏0
  • node異步非阻塞的雜談

    摘要:引言作為服務器的優(yōu)勢就在于適合處理高并發(fā)的請求,對于網(wǎng)站后臺這種密集型的后臺尤其有優(yōu)勢,其核心就在于是一個異步非阻塞模型。關于異步,同步,阻塞,非阻塞這些概念,本文不做討論。另外兩個的調(diào)用時間需要判斷是否都在主線程中被執(zhí)行。 引言 node作為服務器的優(yōu)勢就在于適合處理高并發(fā)的請求,對于web網(wǎng)站后臺這種I/O密集型的后臺尤其有優(yōu)勢,其核心就在于node是一個異步非阻塞模型。關于異步,...

    izhuhaodev 評論0 收藏0

發(fā)表評論

0條評論

0xE7A38A

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<