Promise是ES6新增一个内置类,可以理解为它是承诺者模式,Promise对象用于表示一个异步操作的最终完成(成功或者失败),以及结果的值。它主要是为了有效管理异步编程,存在的目的就是为了解决回调地狱。
什么是回调地狱?
基于ajax的请求,完成需求为请求三个接口(@1:/api/list&@2/api/detail?id=100&@3/api/ranking),带你理解什么是回调地狱。首先先看一段代码:
$.ajax({
url:'api/list',
success(){
// 第一个请求成功,触发了success回调函数
$.ajax({
url:'/api/detail?id=100',
success(){
// 第二个请求成功
$.ajax({
url:'/api/ranking',
success(){
// 第三请求成功
}
})
}
})
}
})
这是ajax的串行:也就是多个请求之间有依赖。只有完成上一个请求,才能发送下一个请求。代码中,代码一层圈套一层。为了实现代码顺序执行而出现的一种操作,它会造成我们的代码可读性非常差,后期不好维护。这就是回调地狱。
创建Promise实例的几种方法:
一:通过new Promise ((executor))
注意:executor函数执行看是否报错,如果报错则返回是失败的,失败的原因就是报错的原因。但是不报错的不一定成功,它会接着走下一步。
在这里小编对executor函数做一个扩展,帮助你更好的掌握Promise
1. 必须传递的是一个函数,不传或者传递其他类型值都会报错
2. new promise的时候会立即把传递的executor函数执行,这个操作是的同步的.
new Promise(()=>{
console.log(1);
});
console.log(2)
//它的输出结果就是1,2
3. 在executor函数中,一般来写一些易怒的编程代码(promise管理异步编程,其实就是把异步编程的代码放在executor中
[executor]函数中有两个形参: resolve/reject(本身也都是个函数)
resolve([value])把时刻状态改为fulfilled,实例值是[value]
reject([reason])把实例状态改为rejected,实例值是[reason]
一旦实例状态被改变为成功和失败,不可以再次更改[executor]函数执行一旦报错,实例的状态也是rejected,实例的值就是报错原因
二:通过.then实例创建
let @p=实例.then([[onfulfilled]],[[onrejected]])
在这里说明一下.then和.catch的区别
.then后面接的是([[onfulfilled]],[[onrejected]])
.catch后面接的是([onjected]) 因为catch会对错误进行兜底,就是抛出的任何异常时都会进入到catch中。
then链具备“穿透性”如果onfulfilled或者onrejected没有设置,则会顺延到下一个then对应的onfufilled或者onrejected上!!
三:通过.catch创建
let @p=实例.catch([[onrejected]])
- @p是执行then/catch返回的新实例
- 不论是onfulfilled还是onrejected执行。我们关注的是执行是否报错,返回值来决定@p的状态和值。方法执行只要报错@p就是rejected,值就是报错的原因,返回值不是一个新的promise实例,则@p就是fulfilled值就是返回结果。如果返回的是一个新的promise实例(@new)则@new的状态和值决定了@p的状态和值
- 如果两个方法中的某个方法没有传递,则"顺延"到下一个[then的穿透机制]
四:创建一个状态为成功的promise实例(fulfilled)
Promise.resolve([[value]])
创建一个状态为失败的promise实例(rejected)
Promise.resolve([[reason]])
Promise.all([[paomise]])
创建一个实例,当[[promises]]当集合中的每一项实例都是成功,最后整体返回的就是成功(值:按照顺序,储存了集合中每一项成功的结果)其中只要又一项是失败的,整体返回就是失败的(值:谁失败,获取的结果就是谁失败的原因,只要有一项失败了,则处理结果就结束了)
五:还有许多创建Promise的方法
Promise.race/any...
前面是关于一些创建Promise的一些基础知识,了解过基础知识,接下来就跟着小编去看一些源码,来帮助你更深层次的掌握Promise
目录
创建Promise实例的几种方法: 一:通过new Promise ((executor))
源码部分
// 首先为了防止冲突,将promise源码采用闭包的形式保护起来
(function () {
/* 核心 */
function Promise(executor) {
// 对Promise进行检测,检测executor是不是一个函数以及检测Promise是不是一个实例
var self = this;
if (typeof executor !== "function") throw new TypeError("Promise resolver is not a function");
if (!(self instanceof Promise)) throw new TypeError("undefined is not a promise");
// 给Promise 设置私有属性
self.state = "pending";
self.result = undefined;
self.onfulfilledCallback = [];
self.onrejectedCallback = [];
var change = function change(state, result) {
// 修改实例的状态和值(同步) & 通知集合中指定的方法执行(异步)
if (self.state !== "pending") return;
self.state = state;
self.result = result;
setTimeout(function () {
var callback = state === "fulfilled" ? self.onfulfilledCallback : self.onrejectedCallback;
for (var i = 0; i < callback.length; i++) {
callback[i](self.result);
}
});
};
// 立即执行executor函数
try {
executor(function resolve(value) {
change('fulfilled', value);
}, function reject(reason) {
change('rejected', reason);
});
} catch (err) {
change('rejected', err);
}
}
Promise.prototype = {
constructor: Promise,
then: function then(onfulfilled, onrejected) {
var self = this;
switch (self.state) {
case "fulfilled":
setTimeout(function () {
onfulfilled(self.result);
});
break;
case "rejected":
setTimeout(function () {
onrejected(self.result);
});
break;
default:
self.onfulfilledCallback.push(onfulfilled);
self.onrejectedCallback.push(onrejected);
}
},
catch: function myCatch() { }//注意catch这里命名方式,遵循js中的命名规范
};
// 暴露API:即支持CommonJS模块规范也支持浏览器直接导入 >处理兼容问题
if (typeof module === "object" && typeof module.exports === "object") module.exports = Promise;
if (typeof window !== "undefined") window.Promise = Promise;
})();