日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 人文社科 > 生活经验 >内容正文

生活经验

异步编程之Promise(2):探究原理

發布時間:2023/11/27 生活经验 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步编程之Promise(2):探究原理 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

異步編程系列教程:

  1. (翻譯)異步編程之Promise(1)——初見魅力
  2. 異步編程之Promise(2):探究原理
  3. 異步編程之Promise(3):拓展進階
  4. 異步編程之Generator(1)——領略魅力
  5. 異步編程之Generator(2)——剖析特性
  6. 異步編程之co——源碼分析

動手實現Promise

在異步編程之Promise(1)里,我是翻譯了一篇文章,里面是探究promise的模式和領略它的魅力。我們可以利用promise,緩解回調函數給我們帶來的回調金字塔。使用鏈式結構書寫,使代碼更加簡潔易懂,易于控制。但是對于構造promise和其內部的實現,卻用草草的一句new Promise()就帶過。這一次,借著閱讀樸靈大神的《深入淺出Node.Js》,我們自己動手實現一個小小的基本的promise吧。

構建Promise對象

首先我們需要回顧一下,一個Promise/A模式和API上是如何定義的:

  • Promise分別有三個狀態:pending初始狀態,fulfilled完成狀態,rejected失敗狀態。
  • 一旦promise是fulfilled狀態或rejected狀態,那么它就是不會再改變的。
  • 具備then()方法,用于接收fulfilled和rejected狀態的回調方法,并在相應狀態下進行觸發。
  • then()方法只允許接受function對象,其余的會被忽略。
  • then()方法會返回Promise對象,提供鏈式調用。
  • then()方法可接收第三個方法,用于支持progress事件的回調方法。

知道我們的Promise對象需要有什么之后,我們就可以開始嘗試寫Promise的構造函數了。還有Promise是基于事件機制的,也可以說是發布/訂閱模式。所以我們為了演示方便,將使用Node里的events模塊。

還不清楚自定義事件的同學,推薦一個視頻給你們入門:阿當大話西游之WEB組件

var events = require('events'); //events模塊
var util = require('util');     //util工具包模塊var MyPromise = function(){events.EventEmitter.call(this); 
};
util.inherits(MyPromise, events.EventEmitter); // 繼承MyPromise.prototype.then = function(resolve, reject, progress){// this.once()是綁定事件被觸發后立即移除事件if(typeof resolve === 'function'){this.once('success', resolve);}if(typeof reject === 'function'){this.once('error', reject);}if(typeof progress === 'function'){// 不需要once()this.on('progress', progress);}return this;
};

由此,我們就實現了Promise/A規范。我們用promise對象的then,用相應的事件存放了各個狀態的回調函數。那接下來,我們就要知道如何觸發這些事件。

構建Deferred對象
---
為了實現事件的觸發,我們需要有一個新的對象Deferred。意思是,延遲對象。

var Deferred = function(){this.state = 'pending';this.promise = new MyPromise();
};Deferred.prototype.resolve = function(obj){this.state = 'fulfilled';this.promise.emit('success', obj);
};
Deferred.prototype.reject = function(err){this.state = 'failed';this.promise.emit('error', err);
};
Deferred.prototype.progress = function(data){this.promise.emit('progress', data);
};

我們可以看到,我們之前定義的promise成為了deferred對象中的一個屬性。然后Deferred對象的方法,都是用來觸發事件來改變promise狀態的。這種模式也稱作Promise/Deffered模式,它是基于發布與訂閱模式,并提供了更加高級的抽象。Deferred對象,用來控制Promise內部,維護Promise狀態。Promise對象,則是作用于外部,通過then(resolve, reject)對外提供接口。

對于上一篇講到的promise化的readJSON,我們可以使用我們定義的Promise/Deferred重寫一遍:

var readJSON = function(filename, encoding){var deferred = new Deferred();fs.readFile(filename, encoding, function(err, res){if(err)return deferred.reject(err);deferred.resolve(JSON.parse(res));});return deferred.promise;
};// 應用
readJSON('data.json', 'utf-8').then(function(res){console.log(res.message); // Hello World!
})

對我來說,我更喜歡Promise/Deferred的實現。因為通過Deferred對象,我們可以很隨心的控制promise的狀態,得到我們想要的樣子。當然喜歡原生ES6的那種為Promise構造函數傳入工廠函數,也是可以自己改造一下的,和回調參數差不多,可以自行嘗試一下。不知道是不是應為我個人水平問題,寫起來覺得亂糟糟。所以我更喜歡Promise/Deferred模式的實現。代碼如下:

// 去掉Deferred對象,直接通過回調參數來確定是resolve還是reject。
var MyPromise = function(factory){events.EventEmitter.call(this);var _this = this;factory && factory(function(res){console.log(res);_this.emit('success', res);}, function(err){_this.emit('error', err);});
};
util.inherits(MyPromise, events.EventEmitter);// 模擬ES6構造函數方法的應用
var readJSON = function(filename, encoding){return new MyPromise(function(resolve, reject){fs.readFile(filename, encoding, function(err, res){if(err)return reject(err);resolve(JSON.parse(res));});});
};readJSON("data.json", 'utf-8').then(function(data){console.log(data.message); // Hello World!
});

我們通過把json解析后傳到resolve()中實現了我們上一篇的readJSON函數promise化的要求!酷~

開始使用Promise

從這兩篇promise的探究路上,如果能體會到其中的奧妙,應該也差不多可以上道了。這個時候在ES6還未普及前,實現完整優秀promise模式可以借助一些promise庫。這里我推薦 Q.js,為了能體現它的高效和優雅,我們借助以往的readJSON例子。

var Q = require('q');
var fs = require('fs');var readFile = function(filename, encoding){var deferred = new Q.defer(); // 獲取Q的deferred對象fs.readFile(filename, encoding, function(err, res){if(err)return deferred.reject(err);deferred.resolve(res);});return deferred.promise;   // 將promise對象return出去,實現鏈式調用
};var readJSON = function(filename, encoding){return readFile(filename, encoding).then(JSON.parse);
};readJSON('data.json', 'utf-8').then(function(data){console.log(data.message); //Hello World!
});

這里并沒有體現優雅,但是可以看到promise/deferred模式的使用。特別是和我一樣喜歡這種模式的同學,簡直不能再爽!當然,說到優雅,我們可以回想一下,每次我們處理fs.readFile()callback時,我們都是重復的有錯誤就reject,沒錯誤就resolve。同樣的邏輯,其實我們是可以封裝起來的,Q就幫我們做到了這一點。

// 改變fs.readFile()
var readFile = function(filename, encoding){var deferred = new Q.defer(); // 獲取Q的deferred對象    fs.readFile(filename, encoding, deferred.makeNodeResolver());return deferred.promise;   // 將promise對象return出去,實現鏈式調用
};

語意可得,弄一個Node式的回調。這個實現其實很簡單,書上也有說。這個就交給各位同學們,自己動手試一試吧~

接下來,會針對我們自己實現的Promise進行拓展,完成我們更多的需求。在此過程中,探究Promise實現原理。為接下來的異步編程學習打下基礎。

再次感謝樸靈老師的《深入淺出Node.Js》。

再次感謝樸靈老師的《深入淺出Node.Js》。

再次感謝樸靈老師的《深入淺出Node.Js》。

重要的話,要說三遍。

轉載于:https://www.cnblogs.com/YikaJ/p/4468987.html

總結

以上是生活随笔為你收集整理的异步编程之Promise(2):探究原理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。