帮你理清学习一个知识点的过程
注意:这篇文章的目的是让你用最快的速度理解 Promise 的核心思想和基本用法,想要了解更多细节全面的使用方式,请阅读官方 API
另外:这篇文章假定你具备最基本的异步编程知识,例如知道什么是回调,知道什么是链式调用,同时具备最基本的单词量,例如 page、user、promise、then、resovle、reject、pay、fix、order 等等,如果你对这些单词非常陌生,那么你需要先花点时间补充一下你的英语,否则你仍然会感觉这篇文章难以理解。
什么是异步操作?
所谓异步操作,指的是可以跟当前程序同时执行的操作。举例:
只要你稍微有点异步编程经验,就应该知道,这两个方法会同时完成。
它们的编写顺序并不会影响它们的执行顺序
我们可以给异步操作做一个简单的定义
当一个操作开始执行后,主程序无需等待它的完成,可以继续向下执行。此时该操作可以跟主程序同就称之为 异步操作。 通常当操作完成时,会执行一个我们事先设定好的回调函数来做后续的处理。时(并发)执行。这种操作我们
我们常见的异步操作例如:
异步会带来什么问题?
比如我们现在有两个动画,需要按顺序来执行,也就是第一个结束,第二个才能开始
这个时候可能有点麻烦,传统的解决方法是通过回调:
这种方案显然不太好,如果有很多异步操作需要顺序执行,就会产生所谓的“回调地狱”
这种代码不管是写起来还是读起来都比较烦人。 我们来看下经过 Promise 改造后的样子(伪代码)
Promise 的使用及原理
要熟练 Promise 的的使用,你必须要先搞懂它解决问题的原理
贴一段实际的 Promise 代码,你来感受一下先:
上面的代码使用了 ES6
的 箭头函数,
虽然大大简化了代码的写法,但对于初级程序猿来讲极不友好
读这种代码简直跟读金刚经差不多。我们把代码还原成ES5
的样子
接下来,我们就按照费曼技巧来一步步的学习 Promise 是如何解决问题的
问题1
作为一个异步函数,尤其像 ajax 这种网络请求,连我自己都不能确定函数的执行时间,Promise 是怎么知道第一个函数什么时候结束的? 然后再开始执行下一个?
Promise 并没有那么神奇,它并不能知道我们的函数什么时候结束,你注意到上面代码中的第3
行了吗
在 ajax 请求结束执行回调的时候,我们调用了一个resolve()
函数,这句代码非常的关键.
这其实就是在通知 Promise,当前这个函数结束啦,你可以开始执行下一个。 这时 Promise 就会去执行 then 里面的函数了。
问题2
, 所以按照你的意思,如果我不调用这个方法,Promise 就不知道这个函数有没有结束,那么 then 里面的函数就不会执行,也就是说我的第二个请求就永远不会发送了呗?
Bingo!! 恭喜你已经学会了逻辑推理+抢答。
问题3
可是这个resolve
函数是从哪来的? 需要我自己定义吗? 从代码上看它好像是个参数,那又是谁传入函数中的?
你得先弄明白 Promise 的基本结构
我们把函数 1 和函数 2 都以参数形式传给了一个 Promise 对象,所以接下来函数 1 和 2 都会由这个 Promise 对象控制, 简单的说,函数 1 和函数 2 都会由 Promise 对象来执行。 所以在函数 1 执行时,参数也当然是由 Promise 对象传递进去的。
问题4
, Promise 对象为啥要在执行第 1 个任务的时候,把这个resolve
函数 传进来,有什么目的?
你说呢?
废屁,知道还用问你?
真是猪脑子,刚才不是已经说了吗? Promise 对象没办法知道我们的异步函数啥时候结束。那我来问你, 如果你去车站接人,可是你又不知道对方何时下车,你会咋办?
把我电话号码给他,快到了打我电话呗
没错,Promise 解决问题也采用了同样的思路。它传进来的 resolve
函数, 就好像一个对讲机,当我们的异步任务要结束时,通过对讲机 来通知 Promise 对象。也就是调用 resolve
方法
懂了,所以这个 resolve 函数,必须在异步任务的最后调用(例如 ajax 的回调方法),相当于告诉 Promise 对象,该任务结束,请开始下一个。
完全正确
问题5
, 所以 Promise 也不过如此嘛,它没有带来什么功能上的革命性变化, 因为使用传统的回调嵌套的方式,同样可以完成效果。 说白了它就是编码方式上的改进??
基本是这样的,但 Promise 带来的编码方式以及异步编程思路上的进步是非常巨大的。
问题6
, 那如果我有 ajaxA、ajaxB、ajaxC 三个异步任务,想按照先 A 后 B 再 C 的顺序执行,像这样写行吗?
不行
靠! 我还没说呢!
那你说
如果我这样写呢?
上面的这种写法是不对的。 Promise 的中文含义是“承诺”,则意味着,每一个 Pormise 对象,代表一次承诺
而每一次承诺,只能保证一个任务的顺序,也就是说
new Promise(A).then(B);
这句话表示, 只能保证 A
和 B
的顺序。
一旦 A
执行完,B
开始后,这次承诺也就兑现了,Promise 对象也就失效了
那如果还有 C 呢? 我们就必须在函数 B 中,重新创建新的 Promise 对象,来完成下一个承诺,具体的写法就像这样:
问题7
, 懂了,那 Promise 还有什么其它强大的功能吗?
有啊,例如: 如果我有 A
, B
, C
三个异步任务,ABC 同时开始执行
当A
,B
,C
三个任务全部都结束时,执任务 D,传统方法实现起来就比较复杂,Promise 就非常简单,就像这样:
问题8
, 那如果我希望A
,B
,C
其中任意一个任务完成,就马上开始任务 D,该怎么做?
评论