Promise及Fetch源码解析
后端的很多语言处理http请求都用上了Promise这种模型, 比如finatra. Promise代表的是一个承诺值或者是一个会抛出的异常对象, 后端可以进行异步处理. 同时, 那万恶的nodejs风格的callback也渐渐被Promise这个模型所替代了. Promise类似状态机, 而且只有三个状态, 并只能进行2种转换
浏览器默认的Promise模型
当前已经有很多基于Promise的js库, 比如q, bluebird等等, 都提供了比较简洁的api来使用Promise.下面的代码例子是浏览器的默认行为
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
var p = new Promise(function(resolve, reject) { // Run your code here var k = true; console.log("My Name is KingDomPan"); // Change the State if (k === true) { resolve("KingDomPan"); // 从pending到fulfilled的状态切换 } else { reject("Also KingDomPan"); } });
p.then(function(input) { console.log("The Return From Resolve Callback " + input); // 触发回调 }, function(input) { console.log("The Return From Reject Callback " + input); }); |
当然了then对象之后的返回还是一个promise, 因此可以持续then的调用
一个Promise的简短实现
这个例子证实了Promise是可以纵向处理异步的, 而不是万恶的callback横向处理
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var Promise = function() { this.thens = []; };
Promise.prototype = { resolve: function() { var t = this.thens.shift(), n; // 通过将当前的thens挂靠在子Promise的thens下实现任务的thenable t && (n = t.apply(null, arguments), n instanceof Promise && (n.thens = thens)); }, then: function(n) { return this.thens.push(n) } }; |
fetch标准源代码解析
当前IE9, Firefox, Chrome基本已经内置Fetch的全局方法, 下面的代码来源于Fetch In Github
- function normalizeName(name) 校验http头字段, 返回小写
- function normalizeValue(value) 字符串化value
- function Headers(headers) 创建http头, 参数可以是Header或者js对象, 内部数据结构是一个map, value对应一个数组
- Headers.prototype
- append 追加http头
- delete 删除http头
- get 获得某个http头的第一个值
- getAll 获得某个http头的全部值, 返回一个数组
- has 检测是否有某个http头
- set 设置某个http头的值, 会覆盖map中对应http头的全部值
- forEach(callback, context) 遍历headers, 首先遍历map中的name, 再遍历取出来的values, 传递到callback中并绑定context(call方法的使用)
- function consumed(body) 设置http体是否被使用, 如果超过一次使用的话就会触发promise的catch进行异常处理
- function fileReaderReady(reader) 返回promise, 当输入流准备就绪, 调用resolve方法进行数据的处理, 异常则进行异常处理. reader是HTML5 FileReader之类的实现
- function readBlobAsArrayBuffer(blob) 调用fileReaderReady对blob进行处理而已
- function readBlobAsText(blob) 调用fileReaderReady对blob进行处理而已
- support对象, 该对象检测是否具有HTML5的属性, 比如support.blob support.formData support.arrayBuffer
- function Body()
- 很明显Body的构造函数
- this.bodyUsed = false;
- this._initBody = function(body)
- this._bodyInit 保存原始body数据
- 判断body类型, 创建this.__bodyXXXX保存body
- this.blob()返回promise处理body数据, 数据字段对应了this.__initBody里面创建的
- this.arrayBuffer() 同上
- this.text() 同上
- this.formData() 调用decode解码而已, 返回Promise
- this.json() 调用JSON.parse()返回json对象而已, 返回Promise
- function normalizeMethod(method) 返回规定的HTTP方法字符串而已
- function Request(input, options) 创建请求对象 这个Request会继承Body
- input 包含url, cookie, method, headers 等等的信息 (如果继承Body的话), 否则就是url(没继承Body)
- options 包含body的可选信息
- 一系列设值操作…….
- Request.prototype.clone
- return new Request(this) 简单明了
- function decode(body) queryString的解码, 返回HTLM5的FormData()对象, 参数是字符串, 即bodyText
- function headers(xhr) 从xhr对象获得所有的响应头, 创建Headers并返回
- Body.call(Request.prototype) 果然Request是直接继承Body的
- function Response(bodyInit, options) Response对象的创建
- options 返回回来的响应头信息
- Body.call(Response.prototype) 果然Response也是直接继承Body的
- Response.prototype.clone() 不废话了
- Response.error = function() 直接在构造函数上创建一error方法返回一个错误的response实例对象
- redirectStatuses 重定向的http状态码
- Response.redirect = function(url, status) {} 返回一个重定向的response
- 给window设置全局对象, 或者nodejs中的global
- self.Headers = Headers;
- self.Request = Request;
- self.Response = Response;
- self.fetch(input, init) 定义伟大的fetch方法
- 返回一个promise
- 初始化请求对象Request
- 创建xhr对象
- onload 验证是不是网络异常, 返回一个Response给Promise的then进行处理
- onerror 网络异常了才会触发这个
- 内部函数responseURL, 主要是为了CORS的安全考虑的
- 将Request的头信息弄到xhr对象里, 发请求
- self.fetch.polyfill = true 最后这个了这个货的一个属性, 我也不知道
posted on 2016-10-31 16:40 zhangzongshan 阅读(371) 评论(0) 收藏 举报
浙公网安备 33010602011771号