ES6 JavaScript Promise的感性认知

by zhangxinxu from http://www.zhangxinxu.com
本文地址:http://www.zhangxinxu.com/wordpress/?p=3975

一、Promise是一种形式

春节假期看了一部电影,《超人-钢铁之躯》,我媳妇没睡着,说明这部电影还不错。其中有句台词印象深刻:“对于没有见过的东西,人会排斥,因为内心会恐惧”。

于是,就有这样一个问题出来了,如果让人快速接受一个新鲜未知、可能会排斥、带来恐惧的东西。

“介绍其强大以及厉害之处?”

比如本文要介绍的Promise, 介绍其如何使用,多么强大?

No, No, No, 这一上来就直奔菊花的节奏显然是会带来痛苦的。

好比超人哥哥,如果对民众大肆宣扬其多么强大——揉不扁、锤不烂,上天入地是小菜。不怕枪、不怕弹,眼睛镭射狂点赞!

民众只会害怕,排斥,认为这是一个怪物。为何?因为缺乏完整的感性认识。相比强大与否,是敌是友,是好事是坏才是让民众接受的最先考虑的,恰好,此时发生了一连串的实际,超人哥哥以行动表明了自己是站在地球这一边的。

于是,美利坚才会如此迅速认可这位超人哥哥。

我们再来看Promise, 对于部分人而言,接触过类似概念或者有类似需求,本身就有感性认识,因此,此物出现的时候,好比久旱逢甘雨,干柴遇烈火,立马high起啊~

但是,大部分的人是第一次触碰Promise的肌肤。因此,在深入介绍之前,感性认识就尤为重要,否则,会害怕,排斥,扔在一边,等着以后吃现成饭。

我们看电影、电视剧时候都会关注剧情简介;授课或演讲时候会先说个大纲。这些其实都是先塑造感性认识,说白了,就是“脑补形象”。

所以,本文不会详细、完整介绍Promise的使用、特点等。这些您可以参考本文末尾留下的相关文章地址。只会让你对Promise有个感性认知,在脑中塑造出一个物体形象,或大叔、或萝莉、或御姐、或多来A梦、或**棒等。这样,才会有兴趣、才会更快的接受相关技术点、功能、使用技巧等。

OK,首先第1点,Promise是一种形式

注意这里的措辞,“Promise是一种形式”,也就是不要把Promise看成是某些方法、函数之类的。类似于不要把“小姐”看成某个人,而是某种职业。

Promise中文有“誓言”、“承诺”之意。从字面意思我们也似乎体会出一点“形式”的味道。但是,注意这里的转折,根据自己的理解,Promise完全不能按照“承诺”来理解,而是要根据其音译——“普罗米修斯”。普罗米修斯是希腊神话故事中的英雄,名字的意思是“先知”。Promise最初的命名是Futures, “未来”,可见Promise含义不是字面的“誓言”“承诺”之类,而是“先知”“未来”的意思。

那该如何理解“先知”,JS与先知有什么关系?

我们都知道,JS是单线程的,也就是一条线下来的,这是代码世界的一条规则。那么现实世界有与之呼应的吗?——人?No, No, 人是多线程的,人可以一边看动作片,一边撸智深。那是什么东西呢?哈,没错,时间,现实世界里,时间这条线就是单线程的,不会出现两条时间线,这种事是会出现在科幻故事里。

人当下所经历的现实世界中,很多行为结果是未知的,不是即时呈现的。例如,今天的NFL超级碗,巨星曼宁率领的野马队与本赛季黑马海鹰队的比赛。这实际上是个异步的过程,某明星压了1000万赌注野马队赢,比赛的结果会影响这位明星状态。这就类似于JS中发送一个异步的Ajax请求,不同的返回值造成不同的影响。

而Promise则扮演了一个“先知”的角色。预先将你的未来告知,规划好你继续的路。你无需等待最终结果出来,你可以继续你现在的生活。用一个简单的图表示就是下面这样:

如果你是一个先知,你是没有等待、异步这种感觉的。这就是Promise的作用,一种“先知”的形式。好比上帝,已经在他的时间维度的一瞬间规划好了你的一生(因为他有先知的能力)(他无需跟着经历你的时间),虽然你自己依然感受到了时间,以及各种变数。

对于JS代码而言,我们就是上帝。我们能够预知代码的走向,并规划好代码的人生。

回到当下,正在电脑前的我们,想想你会经历的事情,可能就会是下面这样子——沿着时间线,一种事情连着另外一件事,每件事都有多种可能的发展:

这就好比JS世界中的异步操作,例如Ajax请求,现实世界中,大部分的操作结果都不是即时显现的(类似Ajax操作),如果用JS表示我们的一生,那就会是一个超级无限长的嵌套。

实际上,无限的嵌套更符合我们当下所感受的世界的理解。既然如此,那为何我们写代码的时候不喜欢一堆嵌套呢?

很简单,我们写代码的时候,是以上帝的身份来处理代码的,我们是造物主;而不是以代码中的角色身份。目前的JS异步回调就是按照代码视角——随着时间推移,代码中的人和物会经历什么什么。那如何变成先知视角呢?很简单,使用Promise! 而这,就是Promise出现的意义:“将异步操作转换成更符合先知视角的形式展现”!

二、Promise-更符合现实世界的直觉认识

我们之于代码为先知,如果我们知晓某一个现实世界故事发展走向,其实我们也是先知。因此,很多时候,除了自己正在经历的未知的经历,我们可以使用Promise将现实世界映射。

早在11年,我写过一篇名叫“关于一个JS功能实现的思维方式”文章,讲的就是如何站在代码的层面,脱离现实世界的思维方式,以空间换时间来更简单实现我们需要的效果。

Promise与之类似,也可以说是一种思维方式的转变,Promise似乎能更好地映射现实世界,使事情的发展更符合我们的直觉(看完本文就知道其含义了~~)。

讲一个现实世界的故事吧。

男神觉得时机成熟了,手捧99朵披着月季的玫瑰向女神求婚:

“小妞妞,嫁给我吧!我发誓,我会对你一辈子好的!”
“这个嘛,你先去问问我爸爸,我大伯以及我大姑的意思,他们全部都认可你,我再考虑考虑!对了,如果我爸没有答复,大伯他们肯定是不会同意的;如果大伯没有答复,大姑也是不会同意的。”

如果你是男神,你会怎么做?

我的第一反应(直觉)是这样的:

  1. 买些好烟好酒登门拜访岳父大人,恳请岳父大人把女儿许配给自己;1日后,得到岳父答复,如果同意,攻略大伯;如果不同意,继续攻略1次,要是还不行,失败告终;
  2. 同上攻略大伯;
  3. 买上等化妆品,然后同上攻略大姑;
  4. 拿着满满的offer拿下女神。

这是我们现实世界思维方式下的直觉反应,很简单的,也很好懂。

但是如果我们使用目前的JS实现,会是怎样?

因为得到长辈同意是需要等待的,而且一次只能攻略一个长辈,而且还能重复攻略。如果我们使用当下的JS去套用现实逻辑,可能就会这样子(无需细看):

男神.请求({姓名: "岳父",成功: 男神.继续请求({姓名: "大伯",成功: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: "求婚失败"})}),失败: 男神.继续请求({姓名: "大伯",成功: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: "求婚失败"})}),失败: "求婚失败"})}),失败: 男神.请求({姓名: "岳父",成功: 男神.继续请求({姓名: "大伯",成功: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: "求婚失败"})}),失败: 男神.继续请求({姓名: "大伯",成功: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: 男神.继续请求({姓名: "大姑",成功: 男神.最终请求({姓名: "女神",成功: "求婚成功",失败: "求婚失败"}),失败: "求婚失败"})}),失败: "求婚失败"})}),失败: "求婚失败"})
})

立马就晕了!

为何按照现实思维,JS呈现的会这么复杂呢?

  1. 代码需要预先设定好未来要发生的事情(先知视角);但是现实世界并不会如此(经历者视角);
  2. 代码中,空间是稀缺资源;而现实世界中,时间才是。

因此,在传统的JS中,类似这种多嵌套,多异步,多发展的,我们需要牺牲(对于程序来讲)微不足道的时间换取代码的空间和易维护性,于是,我可能就会这么实现(也无需细看):

var NanShen = {"身高": 180,"体重": 80,"年薪": "200K",request: function(obj) {// 攻略长辈成功与否随机决定// 成功概率为80%if (Math.random() > 0.2) {obj.success();} else {obj.error();}}
};var Request = function(names, success) {var index = 0, first = 0;var request = function() {if (names[index]) {NanShen.request({name: names[index],success: function() {first = 0;console.log("成功拿下" + names[index]);index++;request();},error: function() {if (first == 1) {console.log("依旧没能拿下" + names[index] + ",求婚失败");    return;} else {console.log("没能拿下" + names[index] + ",再试一次");    }first = 1;request();    }});    } else {success();}};    request();
};Request(["岳父", "大伯", "大姑"], function() {NanShen.request({name: "女神",success: function() {console.log("女神同意,求婚成功!");},error: function() {console.log("女神不同意,求婚失败!");}});
});

上面代码通过异步回调,有效重复利用了JS代码,实现了男神的求婚历程。

您可以狠狠地点击这里:传统JS思维下实现的求婚历程表现

男神的每次攻略成功率是80%, 因此,其攻略结果可能是这样:

或者这样:

或者这样:

等。自己进入demo死命刷新测试自己人品吧~

————–低调的分隔线————-

不能因为本文主角是Promise就厚此薄彼,上面的JS实现是很赞的,以一种带有Promise的味道将多条件多异步的复杂世界用JS呈现出来,也是一种很巧妙的形式转化,套个噱头应该可以叫做“xxx模式”,呵呵~

然后,上面方法,依次执行的触发依然在回调中,其实并不符合我们现实的思考。我们可能希望得到的代码具有如下与现实世界统一的思维:“搞定岳父→搞定大伯→搞定大姑→搞定女神”,但是,上面的实现却看不出这样的思维。而Promise这种形式可以让代码呈现更符合真实世界的直觉。在这个故事里,女神其实已经把故事的走向全部告诉你了,这种情况下,我们其实已经知晓了未来,我们已经是先知,显然,使用Promise是很可行的。

那使用Promise该是什么模样呢?可参考下面的代码以及demo.

// 男神的各项参数
var NanShen = {"身高": 180,"体重": 80,"年薪": "200K",request: function(obj) {// 成功与否随机决定// 执行成功的概率为80%if (Math.random() > 0.2) {obj.success();} else {obj.error();}}
};var Request = function(name) {return new Promise(function(resolve, reject) {var failed = 0, request = function() {            NanShen.request({name: name,success: function() {console.log(name + "攻略成功!");failed = 0;resolve();},error: function() {if (failed == 0) {console.log("第一次攻略" + name + "失败,重试一次!");failed = 1;// 重新攻略一次request();                       } else {console.log("依然没有拿下" + name + ",求婚失败!");reject();}}});};request();});
};Request("岳父")                                // 搞定岳父,然后...
.then(function() { return Request("大伯"); })  // 搞定大伯,然后...
.then(function() { return Request("大姑"); })  // 搞定大姑,然后...
.then(function() {                            // 长辈们全部KO后,攻略女神NanShen.request({name: "女神",success: function() {console.log("女神同意,求婚成功!");},error: function() {console.log("女神不同意,求婚失败!");}});
});

代码没必要细看。等以后Promise规范成熟之后再细细研究。

哈,忘记demo了,您可以狠狠地点击这里:男神求婚历程的Promise实现

一样的风格,一样的味道,一样的随机攻略结果,例如像下面这样死在大伯手上:

虽然代码量和传统JS实现不分伯仲,但是,注意这里,下面截图所示这圈代码:

截图上的文字是:

对于先知的我们,故事的安排在脑中是即时出现的,而非实际上的异步发生。因此,作为创世的编程者而言,这种与瞬间思考所同步的代码更符合现实世界下的思考方式。因此,更易读更易于理解。

无论是代码世界中的编程还是现实世界的讲故事,我们都是一个先知的角色(除非你能让机器自我学习,无法预知其走向),都是Promise.

现实世界中,我们要讲一个故事,都是一瞬间在脑中知晓(没有异步,等待时间经历的过程),例如教授死了,炸鸡啤酒女会哭得死去活来。在写代码逻辑的时候,脑中的反应也是如此,一瞬间知晓逻辑变化,if(Jiaoshou == "dead") { crying~ }, 是先知。因此,我们更乐意看到符合我们瞬时思维的代码呈现,而不是符合实际发展的代码呈现。

先知思维的代码呈现就是Promise形式;当局者思维的代码呈现就是异步回调形式。

如果套用求婚的故事,则:

  • 先知思维(第三人称视角)——搞定岳父→搞定大伯→搞定大姑→搞定女神
  • 当局者思维(第一人称视角)——去搞定岳父→…等待期…结果来了…→去搞定大伯→…等待期…结果来了…→去搞定大姑→…等待期…结果来了…→去搞定女神→…等待期…结果来了…

前者是先知是上帝,在规划;后者是凡人,在经历。

Codeing以及讲故事都是规划,因此,Promise这种先知形式会让代码更符合我们的认知。说白了就是更好懂,更好维护,可以怎么想就怎么写,而无需写着写着发现丫的需要嵌套需要再套一个函数做回调。

三、结语以及Promise其他相关

ES6中除了Promise, 还有其他一些高级的东西,例如Generatorletfor-of. 不过先暂时放在一边,回头再掌握。

还是那句话,Promise只是让我们当下的JS换了一种形式实现,更符合编程时候的思考角度与方式。因此,通过特定的转换,我们也可以让不支持Promise的低版本浏览器支持之。您可以试试在页面引入如下JS:

<script src="http://s3.amazonaws.com/es6-promises/promise-0.1.1.min.js"></script>

GitHub点击这里。

这也是Promise有众多关注的原因之一。

人总是有差异的。看到一件事物总是会有不同的认知的。例如,看到一幅盛开的菊花的图片,有人会认为这是菊花,还有人会这是“菊花”。对于Promise也是如此。但是,无论你怎么思考,符合你自己的思维方式,适合你自己内心世界的都是正确的认知。So, 又会被人批评啰嗦的本文所阐述的一些感性认知,如果您有不同的看法,有不同的形象认知,都是OK的,是很赞的,也是希望能有不同的感性认知的!

感性这东西,就像发动机里的润滑油,寒冬里的温暖阳光,会让事情变得妙不可言。

欢迎交流,欢迎探讨。

相关文章

  • http://www.sitepoint.com/overview-javascript-promises/
  • http://www.html5rocks.com/zh/tutorials/es6/promises/
  • http://www.sitepoint.com/deeper-dive-javascript-promises/
  • http://www.sitepoint.com/six-things-might-know-promises/

本文为原创文章,会经常更新知识点以及修正一些错误,因此转载请保留原出处,方便溯源,避免陈旧错误知识的误导,同时有更好的阅读体验。
本文地址:http://www.zhangxinxu.com/wordpress/?p=3975

ES6 JavaScript Promise的感性认知相关推荐

  1. 视频教程-Javascript - Es6之Promise精讲系列-JavaScript

    Javascript - Es6之Promise精讲系列 全栈开发工程师,现职于北京一家学院的全栈教学主任. 8年前端开发经验.4年移动端开发经验.4年UI设计经验.3年一线教学经验. 精通Node. ...

  2. 【ES6】Promise对象详解

    [ES6]Promise对象详解 一.Promise对象的含义 二.Promise对象的用法 三.Promise对象的几个应用[重点] 1.时间延迟函数 2.图片异步加载 查看更多ES6教学文章: 参 ...

  3. 浅谈ES6原生Promise

    ES6标准出炉之前,一个幽灵,回调的幽灵,游荡在JavaScript世界. 正所谓: 世界本没有回调,写的人多了,也就有了})})})})}). Promise的兴起,是因为异步方法调用中,往往会出现 ...

  4. 谈谈 ES6 的 Promise 对象

    2019独角兽企业重金招聘Python工程师标准>>> 谈谈 ES6 的 Promise 对象 异步编程 promise es6 javascript 前言 开篇首先设想一个日常开发 ...

  5. 用es5实现es6的promise,彻底搞懂promise的原理

    1.promise的含义 Promise 是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Pr ...

  6. Javascript Promise用法详解

    1.约定 本文的 demo 代码有些是伪代码,不可以直接执行. 没有特殊说明,本文所有 demo 都是基于 ES6 规范. Object.method 代表是静态方法, Object#method 代 ...

  7. JavaScript Promise返回值详解

    JavaScript Promise返回值详解 Promise回顾 Promise回调函数返回非Promise值 Promise回调函数返回Promise对象 Promise回调函数中抛出错误 总结 ...

  8. 自学-ES6篇-Promise对象

    1.Promise Promise是异步编程的一种解决方案,比传统的解决方案--回调函数和事件--更合理和更强大.它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise ...

  9. 【ES6】Promise用法

    promise理解及使用 Promise解决的问题--异步 Promise的基本用法 异步操作拒绝及中断调用链 ES6对Promise/A+的扩展 Promise.all的扩展 Promise.rac ...

最新文章

  1. .NET Framework 4.0的新特性
  2. 分子偶极矩大小如何判断_润滑油粘度大小该如何判断你知道吗?
  3. 中美领军全球AI竞赛,人工智能被高估了么?
  4. 高速串行总线的设计基础(一)同步时序模型介绍
  5. MVVM框架下,WPF实现Datagrid里的全选和选择
  6. 编码过程中的问题总结
  7. model.train_on_batch介绍【TensorFlow2入门手册】
  8. ios跨线程通知_iOS多线程开发(三)---Run Loop(一)
  9. java弹窗 触发事件_关于ElementUI中MessageBox弹框的取消键盘触发事件(enter,esc)关闭弹窗(执行事件)的解决方法...
  10. [css] 说说你对sass的嵌套规则的理解?
  11. C语言-07其它相关
  12. 使用generator自动生成mybatis model、mapper.xml、mapper等(转)
  13. 第十一天-linux的硬链接和软连接的区别
  14. java 链式写法_JAVA中实现链式操作(方法链)的简单例子
  15. 最基础的傅里叶变换公式推导
  16. 中国实验室玻璃器皿行业市场供需与战略研究报告
  17. 【深度学习 理论】Brief Introduction of Deep Learning
  18. Java入门教程笔记07(面向对象基础)
  19. @property python知乎_知乎某处XSS+刷粉超详细漏洞技术分析
  20. [BX]、loop、inc、dec指令

热门文章

  1. python画哪吒_哪吒票房逼近30亿,python爬取哪吒短评分析
  2. LaTeX 使用tips与EDAS论文提交
  3. Hadoop实现数据清洗ETL
  4. Unity控制窗口全屏显示
  5. php在线留言,PHP在线提交留言直接发到邮箱
  6. PADS9.5软件安装教程|兼容WIN10
  7. MySQL模糊查询 结果按匹配度 排序
  8. java 相似度匹配算法
  9. 使用远程工具RDO:远程计算机需要网络级别身份验证,而您的计算机不支持该验证解决办法
  10. Unable to start service Intent U=0: not found