以前一直对于promise,就是一顿用,历来没有深究其内部原理,无心间看到一些关于promise输出顺序的题目也是一顿瞎猜。。。哈哈,在个人同事对promise进行分享以后(虽然我由于起不来没有听),可是学习promise的意识就此种下。。。啥也不说了,就是学。。。css
带着疑问去学习:jquery
- promise是干什么的?
- promise有哪些方法?
- pomise如何实现链式调用?以前jquery也是能够链式调用,他们以前的区别?
- promise的then方法是如何肯定在前面resolve或者reject执行完拿到结果再执行的?
- 手写一个知足promiseA+的promise方法(写了一下,发现没法经过promiseA+的测试用例,已放弃,拿着别人写的仔细看了一下)
promise是一种异步编程的解决方案,它能够实现把异步操做按照同步操做的流程表达出来。它能够接收一个异步请求,而后在其then方法能够获得前面异步请求的结果进行后续操做,使用链式调用的方式将异步请求的结果按照同步的方式表达出来。编程
1. promise只是异步编程的解决方案,自身并非异步请求,在new Promise()内部传的方法会当即执行。数组
const promise = new Promise(function (resolve, reject) {
console.log('12')
setTimeout(function () {
resolve('success')
}, 1000)
})
promise.then(function (success) {
console.log(success)
})
// 执行结果: 先输出12,过了一秒后再输入success
复制代码
2. new Promise内的resolve是异步执行的,且全部then方法和catch方法也会将在当前脚本全部同步任务执行完才会执行promise
const myPromise = new Promise(function (resolve, reject) {
console.log('1')
resolve('2')
console.log('3')
})
myPromise.then(function (success) {
console.log(success)
})
setTimeout (function () {
// 这里能够看到前面myPromise已经resolved了,可是他仍是会在最后执行,由于then内部也是异步操做
myPromise.then(function (success) {
console.log('again', success)
})
console.log('4')
}, 1000)
console.log('5')
// 执行结果是: 1 3 5 2 4 again 2
复制代码
const promise = new Promise(function(resolve, reject) {
if (/* 异步操做成功 */){
resolve(value);
} else {
reject(error);
}
});
promise.then(function(value) {}, function (error) {})
复制代码
基本用法简单归纳一下:bash
then()和catch()默认返回的都是一个Promise实例对象,即便return了别的信息,返回的仍然是Promise实例对象,仍是且这个promise的状态都是resolve异步
无论Promise对象最后状态如何,finally方法都会执行,(promise是pedding状态不会执行finally方法,resolve和reject都会执行)ide
将现有对象转换为Promise对象异步编程
将多个Promise实例包装成一个新的Promise实例。函数
var p1 = new Promise((resolve) => {
setTimeout(() => {
resolve('p1')
}, 1000)
})
var p2 = new Promise((resolve) => {
setTimeout(() => {
resolve('p2')
}, 2000)
})
var p3 = new Promise((resolve) => {
setTimeout(() => {
resolve('p3')
}, 3000)
})
var p = Promise.all([p1, p2, p3]).then((value) => {
console.log(value)
}).catch((err) => {
console.log(err)
})
// 返回值:['p1', 'p2', 'p3']
复制代码
这里Promise的状态是由p1,p2,p3共同决定的:
将现有对象转换为Promise对象,只要p一、p二、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
在每一次执行Promise的then或者catch方法后,返回的都是一个新的Promise实例化对象,使得又一次可使用then或者catch方法,而且能够拿到上一次then方法return回来的值。
例如:
then内部的函数return了一个数值a。咱们发现then方法执行完,返回的是一个新的promise实例,其promisevalue为a
根据以上铺垫,咱们就知道,其链式调用就是经过then和catch方法内部return new Promise()
经过return this,在其原型方法执行结束都会teturn其自己
var Jquery = function () {
}
Jquery.prototype = {
css: function (attr, data) {
return this
},
hide: function () {
console.log('hide')
return this
}
}
var jq = new Jquery()
jq.css().hide()
复制代码
这里jq调用了css方法,首先会在jq上找css方法,没有找到,而后就去其构造函数Jquery的原型中找,找到css方法并执行,在原型css方法里return this中的this指向的是jq
promise执行了then或者catch方法后,每一次返回的是一个新的Promise实例,jquey一直返回的都是其自己
这里学习了一下别人写的promise,经过这个学习到了一些,中间关于这部分的代码
const PENDING = 'pending'
const RESOLVED = 'resolved'
const REJECTED = 'rejected'
// promise 对象上有resolve,reject,all,race等方法,原型上有then,catch,finally方法
class myPromise {
constructor (fn) {
// 首先须要判断fn是不是一个函数
if (typeof fn != 'function') return 'fn is not function'
this.PromiseStatus = PENDING
this.PromiseValue = null
this.PromiseReason = null
this.onResolvedCallbacks = []
this.onRejectedCallbacks = []
const resolve = value => { // 代码块一
if(value instanceof Promise) {
return value.then(resolve, reject);
}
// new Promise构造函数传进来的函数fn会当即执行,可是在new Promise内resolve和reject是异步操做(如何作到异步操做 =>使用setTimeout确保new Promise后的then和catch方法会在fn函数执行完才触发)
setTimeout(() => {
if (this.PromiseStatus == PENDING) {
this.PromiseStatus = RESOLVED
this.PromiseValue = value
this.onResolvedCallbacks.map(cb => {
this.PromiseValue = cb(this.PromiseValue)
})
}
})
}
const reject = value => {
setTimeout(() => {
if (this.PromiseStatus == PENDING) {
this.PromiseStatus = REJECTED
this.PromiseReason = value
this.onRejectedCallbacks.map(cb => {
this.PromiseReason = cb(this.PromiseReason)
})
}
})
}
try { // 代码块二
// 当即执行new Promise内的
fn(resolve, reject)
} catch (err) {
reject(err)
}
}
then (onResolved, onRejected) { // 代码块三
onResolved = typeof onResolved === 'function' ? onResolved : function (v) { return v}
onResolved = typeof onRejected === 'function' ? onRejected : function (v) { return v}
console.log('this.PromiseStatus', this.PromiseStatus)
if (this.PromiseStatus === RESOLVED) { // 代码块三 条件一
return new myPromise((resolve, reject) => {
// 何时会出现resolve一进来就变成RESOLVED或者REJECTED? 同一个Promise实例被屡次调用其then时,这样会走下面的逻辑,为肯定then内部仍是会异步执行,使用setTimeout
setTimeout(() => {
try {
// 执行then内部的方法
let x = onResolved(this.PromiseValue)
resolvePromise(newPromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
})
}
if (this.PromiseStatus === REJECTED) { // 代码块三 条件二
return new myPromise((resolve, reject) => {
setTimeout(() => {
try {
let x = onRejected(this.PromiseReason)
resolvePromise(newPromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
})
}
// 当没有触发resolve或者reject时,将onResolved和onRejected存放在onResolvedCallbacks/onRejectedCallbacks集合中
if (this.PromiseStatus === PENDING) { // 代码块三 条件三
return new myPromise ((resolve, reject) => {
this.onResolvedCallbacks.push(value => {
try {
let x = onResolved(value)
resolvePromise(newPromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
this.onRejectedCallbacks.push(reason => {
try {
let x = onRejected(reason)
resolve(x)
} catch (err) {
reject(err)
}
})
})
}
}
}
复制代码
根据以上代码,咱们进行简单的分析:
new myPromise(function (resolve, reject) {
console.log(1)
resolve(2)
}).then(function (success) {
console.log(success)
})
复制代码
上面的代码中,首先构造函数初始化一些值
this.PromiseStatus = PENDING // 初始promise的状态
this.PromiseValue = null // 初始promise resolve状态时的value值
this.PromiseReason = null // 初始promise reject状态时的value值
this.onResolvedCallbacks = [] // 存储resolved状态对应的onResolvedCallbacks事件数组
this.onRejectedCallbacks = [] // 存储rejected状态对应的onRejectedCallbacks事件数组
复制代码
例如上面简单的例子:其经历的步骤有:
首先进入myPromise构造函数内,进入代码块二,当即执行myPromise传进来的函数fn,这里PromiseStatus=PENDING
try { // 代码块二
// 当即执行new Promise内的
fn(resolve, reject)
} catch (err) {
reject(err)
}
复制代码
执行fn时,进一步执行resolve函数,进入代码块一,这里首先对resolve传进来的参数进行了类型判断,而后咱们能够看到setTimeout代码,这里将setTimeout内部的事件放在eventLoop的最后。这里PromiseStatus=PENDING
setTimeout(() => {
if (this.PromiseStatus == PENDING) {
this.PromiseStatus = RESOLVED
this.PromiseValue = value
this.onResolvedCallbacks.map(cb => {
this.PromiseValue = cb(this.PromiseValue)
})
}
})
复制代码
触发myPromise的then方法,进入到代码块三,进行条件判断,进入到代码块三的 条件三,返回一个新的myPromise实例,这里会当即执行下面代码
this.onResolvedCallbacks.push(value => {
try {
let x = onResolved(value)
resolvePromise(newPromise, x, resolve, reject);
} catch (err) {
reject(err)
}
})
复制代码
这个操做就是向onResolvedCallbacks里push一个函数
上述操做结束后,再执行前面放在eventLoop最后的事件
setTimeout(() => {
if (this.PromiseStatus == PENDING) {
this.PromiseStatus = RESOLVED
this.PromiseValue = value
this.onResolvedCallbacks.map(cb => {
this.PromiseValue = cb(this.PromiseValue)
})
}
})
复制代码
这里找到更改了PromiseStatus的状态,并执行onResolvedCallbacks数组中的函数,这个函数是以前代码块三中的
value => {
try {
let x = onResolved(value)
resolvePromise(newPromise, x, resolve, reject);
} catch (err) {
reject(err)
}
}
复制代码
因此,promise的then方法是如何肯定在前面resolve或者reject执行完拿到结果再执行的,分两种状况:
a = new Promise((resolve, reject) => {
resolve(1)
})
复制代码