当前位置: 首页 > news >正文

东钱湖镇建设局网站怎么开发小程序

东钱湖镇建设局网站,怎么开发小程序,做得比较好的公司网站,wordpress标签管理随着浏览器端异步操作复杂程度的日益增加#xff0c;以及以 Evented I/O 为核心思想的 NodeJS 的持续火爆#xff0c;Promise、Async 等异步操作封装由于解决了异步编程上面临的诸多挑战#xff0c;得到了越来越广泛的应用。本文旨在剖析 Promise 的内部机制#xff0c;从实… 随着浏览器端异步操作复杂程度的日益增加以及以 Evented I/O 为核心思想的 NodeJS 的持续火爆Promise、Async 等异步操作封装由于解决了异步编程上面临的诸多挑战得到了越来越广泛的应用。本文旨在剖析 Promise 的内部机制从实现原理层面深入探讨从而达到“知其然且知其所以然”在使用 Promise 上更加熟练自如。如果你还不太了解 Promise推荐阅读下 promisejs.org 的介绍。 是什么 Promise 是一种对异步操作的封装可以通过独立的接口添加在异步操作执行成功、失败时执行的方法。主流的规范是 Promises/A。 Promise 较通常的回调、事件/消息在处理异步操作时具有显著的优势。其中最为重要的一点是Promise 在语义上代表了异步操作的主体。这种准确、清晰的定位极大推动了它在编程中的普及因为具有单一职责而且将份内事做到极致的事物总是具有病毒式的传染力。分离输入输出参数、错误冒泡、串行/并行控制流等特性都成为 Promise 横扫异步操作编程领域的重要砝码以至于 ES6 都将其收录并已在 Chrome、Firefox 等现代浏览器中实现。 内部机制 自从看到 Promise 的 API我对它的实现就充满了深深的好奇一直有心窥其究竟。接下来将首先从最简单的基础实现开始由浅入深的逐步探索剖析每一个 feature 后面的故事。 为了让语言上更加准确和简练本文做如下约定 Promise代表由 Promises/A 规范所定义的异步操作封装方式promise代表一个 Promise 实例。基础实现 为了增加代入感本文从最为基础的一个应用实例开始探索通过异步请求获取用户id然后做一些处理。在平时大家都是习惯用回调或者事件来处理下面我们看下 Promise 的处理方式 // 例1function getUserId() {return new Promise(function (resolve) {// 异步请求Y.io(/userid, {on: {success: function (id, res) {resolve(JSON.parse(res).id);}}});}); }getUserId().then(function (id) {// do sth with id });JS Bin getUserId 方法返回一个 promise可以通过它的 then 方法注册在 promise 异步操作成功时执行的回调。自然、表意的 API用起来十分顺手。 满足这样一种使用场景的 Promise 是如何构建的呢其实并不复杂下面给出最基础的实现 function Promise(fn) {var value null,deferreds [];this.then function (onFulfilled) {deferreds.push(onFulfilled);};function resolve(value) {deferreds.forEach(function (deferred) {deferred(value);});}fn(resolve); }代码很短逻辑也非常清晰 调用then方法将想要在 Promise 异步操作成功时执行的回调放入 deferreds 队列创建 Promise 实例时传入函数被赋予一个函数类型的参数即 resolve用以在合适的时机触发异步操作成功。真正执行的操作是将 deferreds 队列中的回调一一执行resolve 接收一个参数即异步操作返回的结果方便回调使用。有时需要注册多个回调如果能够支持 jQuery 那样的链式操作就好了事实上这很容易 this.then function (onFulfilled) {deferreds.push(onFulfilled);return this; };这个小改进带来的好处非常明显当真是一个大收益的小创新呢 // 例2getUserId().then(function (id) {// do sth with id }).then(function (id) {// do sth else with id });JS Bin 延时 如果 promise 是同步代码resolve 会先于 then 执行这时 deferreds 队列还空无一物更严重的是后续注册的回调再也不会被执行了 // 例3function getUserId() {return new Promise(function (resolve) {resolve(9876);}); }getUserId().then(function (id) {// do sth with id });JS Bin 此外Promises/A 规范明确要求回调需要通过异步方式执行用以保证一致可靠的执行顺序。为解决这两个问题可以通过 setTimeout 将 resolve 中执行回调的逻辑放置到 JS 任务队列末尾 function resolve(value) {setTimeout(function () {deferreds.forEach(function (deferred) {deferred(value);});}, 0); }引入状态 Hmm好像存在一点问题如果 Promise 异步操作已经成功之后调用 then 注册的回调再也不会执行了而这是不符合我们预期的。 解决这个问题需要引入规范中所说的 States即每个 Promise 存在三个互斥状态pending、fulfilled、rejected它们之间的关系是 经过改进后的代码 function Promise(fn) {var state pending,value null,deferreds [];this.then function (onFulfilled) {if (state pending) {deferreds.push(onFulfilled);return this;}onFulfilled(value);return this;};function resolve(newValue) {value newValue;state fulfilled;setTimeout(function () {deferreds.forEach(function (deferred) {deferred(value);});}, 0);}fn(resolve); }JS Bin resolve 执行时会将状态设置为 fulfilled在此之后调用 then 添加的新回调都会立即执行。 似乎少了点什么哦是的没有任何地方将 state 设为 rejected这个问题稍后会聊方便聚焦在核心代码上。 串行 Promise 在这一小节将要探索的是 Promise 的 Killer Feature串行 Promise这是最为有趣也最为神秘的一个功能。 串行 Promise 是指在当前 promise 达到 fulfilled 状态后即开始进行下一个 promise后邻 promise。例如获取用户 id 后再根据用户 id 获取用户手机号等其他信息这样的场景比比皆是 // 例4getUserId().then(getUserMobileById).then(function (mobile) {// do sth with mobile});function getUserMobileById(id) {return new Promise(function (resolve) {Y.io(/usermobile/ id, {on: {success: function (i, o) {resolve(JSON.parse(o).mobile);}}});}); }JS Bin 这个 feature 实现的难点在于如何衔接当前 promise 和后邻 promise。 首先对 then 方法进行改造 this.then function (onFulfilled) {return new Promise(function (resolve) {handle({onFulfilled: onFulfilled || null,resolve: resolve});}); };function handle(deferred) {if (state pending) {deferreds.push(deferred);return;}var ret deferred.onFulfilled(value);deferred.resolve(ret); }then 方法改变很多这是一段暗藏玄机的代码 then 方法中创建了一个新的 Promise 实例并作为返回值这类 promise权且称作 bridge promise。这是串行 Promise 的基础。另外因为返回类型一致之前的链式执行仍然被支持handle 方法是当前 promise 的内部方法。这一点很重要看不懂的童鞋可以去补充下闭包的知识。then 方法传入的形参 onFullfilled以及创建新 Promise 实例时传入的 resolve 均被压入当前 promise 的 deferreds 队列中。所谓“巧妇难为无米之炊”而这正是衔接当前 promise 与后邻 promise 的“米”之所在。新增的 handle 方法相比改造之前的 then 方法仅增加了一行代码 deferred.resolve(ret);这意味着当前 promise 异步操作成功后执行 handle 方法时先执行 onFulfilled 方法然后将其返回值作为实参执行 resolve 方法而这标志着后邻 promise 异步操作成功接力工作就这样完成啦 以例 2 代码为例串行 Promise 执行流如下 这就是所谓的串行 Promise当然不是这些改造只是为了为最后的冲刺做铺垫它们在重构底层实现的同时兼容了本文之前讨论的所有功能。接下来画龙点睛之笔–最后一个方法 resolve 是这样被改造的 function resolve(newValue) {if (newValue (typeof newValue object || typeof newValue function)) {var then newValue.then;if (typeof then function) {then.call(newValue, resolve);return;}}state fulfilled;value newValue;setTimeout(function () {deferreds.forEach(function (deferred) {handle(deferred);});}, 0); }啊哈resolve 方法现在支持传入的参数是一个 Promise 实例了以例 4 为例执行步骤如下 getUserId 生成的 promise 简称 getUserId promise异步操作成功执行其内部方法 resolve传入的参数正是异步操作的结果 userid调用 handle 方法处理 deferreds 队列中的回调getUserMobileById 方法生成新的 promise简称 getUserMobileById promise执行之前由 getUserId promise 的 then 方法生成的 bridge promise 的 resolve 方法传入参数为 getUserMobileById promise。这种情况下会将该 resolve 方法传入 getUserMobileById promise 的 then 方法中并直接返回在 getUserMobileById promise 异步操作成功时执行其 deferreds 中的回调getUserId bridge promise 的 resolve 方法最后执行 getUserId bridge promise 的后邻 promise 的 deferreds 中的回调上述步骤实在有些复杂主要原因是 bridge promise 的引入。不过正是得益于此注册一个返回值也是 promise 的回调从而实现异步操作串行的机制才得以实现。 一图胜千言下图描述了例 4 的 Promise 执行流 失败处理 本节处理之前遗留的 rejected 状态问题。在异步操作失败时标记其状态为 rejected并执行注册的失败回调 // 例5function getUserId() {return new Promise(function (resolve, reject) {// 异步请求Y.io(/userid/1, {on: {success: function (id, res) {var o JSON.parse(res);if (o.status 1) {resolve(o.id);} else {// 请求失败返回错误信息reject(o.errorMsg);}}}});}); }getUserId().then(function (id) {// do sth with id }, function (error) {console.log(error); });JS Bin 有了之前处理 fulfilled 状态的经验支持错误处理变得很容易。毫无疑问的是这将加倍 code base在注册回调、处理状态变更上都要加入新的逻辑 function Promise(fn) {var state pending,value null,deferreds [];this.then function (onFulfilled, onRejected) {return new Promise(function (resolve, reject) {handle({onFulfilled: onFulfilled || null,onRejected: onRejected || null,resolve: resolve,reject: reject});});};function handle(deferred) {if (state pending) {deferreds.push(deferred);return;}var cb state fulfilled ? deferred.onFulfilled : deferred.onRejected,ret;if (cb null) {cb state fulfilled ? deferred.resolve : deferred.reject;cb(value);return;}ret cb(value);deferred.resolve(ret);}function resolve(newValue) {if (newValue (typeof newValue object || typeof newValue function)) {var then newValue.then;if (typeof then function) {then.call(newValue, resolve, reject);return;}}state fulfilled;value newValue;finale();}function reject(reason) {state rejected;value reason;finale();}function finale() {setTimeout(function () {deferreds.forEach(function (deferred) {handle(deferred);});}, 0);}fn(resolve, reject); }增加了新的 reject 方法供异步操作失败时调用同时抽出了 resolve 和 reject 共用的部分形成 finale 方法。 错误冒泡是上述代码已经支持且非常实用的一个特性。在 handle 中发现没有指定异步操作失败的回调时会直接将 bridge promise 设为 rejected 状态如此达成执行后续失败回调的效果。这有利于简化串行 Promise 的失败处理成本因为一组异步操作往往会对应一个实际功能失败处理方法通常是一致的 // 例6getUserId().then(getUserMobileById).then(function (mobile) {// do sth else with mobile}, function (error) {// getUserId或者getUerMobileById时出现的错误console.log(error);});JS Bin 异常处理 如果在执行成功回调、失败回调时代码出错怎么办对于这类异常可以使用 try-catch 捕获错误并将 bridge promise 设为 rejected 状态。handle 方法改造如下 function handle(deferred) {if (state pending) {deferreds.push(deferred);return;}var cb state fulfilled ? deferred.onFulfilled : deferred.onRejected,ret;if (cb null) {cb state fulfilled ? deferred.resolve : deferred.reject;cb(value);return;}try {ret cb(value);deferred.resolve(ret);} catch (e) {deferred.reject(e);} }如果在异步操作中多次执行 resolve 或者 reject 会重复处理后续回调可以通过内置一个标志位解决。 总结 Promise 作为异步操作的一种 Monad魔幻一般的 API 让人难以驾驭。本文从简单的基础实现起步逐步添加内置状态、串行、失败处理/失败冒泡、异常处理等关键特性最终达到类似由 Forbes Lindesay 所完成的一个简单 Promise 实现的效果。在让我本人更加深刻理解 Promise 魔力之源的同时希望为各位更加熟练的使用这一实用工具带来一些帮助。 预告 下一篇关于 Promise 的文章中将重点关注高阶应用的一些场景例如并行 Promise、基于 Promise 的异步操作流封装、语法糖等。敬请期待。 参考 Introduction to PromisesJavaScript Promises … In Wicked DetailA Gentle Introduction to Monads in JavaScript
http://www.pierceye.com/news/640405/

相关文章:

  • 织梦网站搜索怎么做爱拍怎么创建wordpress
  • 阿里云多网站建设绵阳专门做网站的公司有哪些
  • 网站推广的基本方法对于大部分网站来说都是适用的深圳华强北网站建设
  • 网校网站毕业设计的方案网站如何做外链教程视频
  • poiplayer wordpress广州企业网站seo
  • wordpress翻页数字广州网站整站优化
  • 动漫网站设计与实现wordpress禁止留言网址
  • 网站开发交流培训机构网站制作
  • 网站安全建设模板下载百度推广免费建站
  • 开发网站公司都需要什么岗位人员郑州最好的妇科医院
  • 河北专业网站建设公司推荐温州网站建设公司有哪些
  • flash布局 的优秀网站大连网络广告
  • 网站运营seo浙江台州做网站的公司
  • 网站设计师培训学校京东联盟如何做查优惠卷的网站
  • 安全证查询官网安徽seo团队
  • 网站备案怎么注销天工网官方网站
  • 做网站去哪推广好安徽义信建设网站
  • 金乡网站建设哪家便宜示范建设验收网站
  • 西部数码网站管理助手 ftpwordpress 店铺
  • 怎样找到黄页网站唯品会 一家专门做特卖的网站
  • 企业数字展厅设计信息流优化师是干什么的
  • 网站建设福永附近网络公司怎样建设网站最好
  • 水利建设公共服务平台网站网站开发需要用什么
  • 2015做哪个网站致富网站点击量怎么看
  • 好学校平台网站模板下载wordpress 手机 登陆不了
  • 2021不良正能量免费网站app食品网站设计
  • ps做的网站林州网站建设哪家好
  • wordpress站点logo设置简易微网站模板
  • 做网站这么做网络工程师招聘
  • 如何做企业交易网站wordpress主题 ie打不开主页