Promise
是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
- promise有三种状态:
状态一旦改变就不会再发生改变
- pending:初始状态,不是成功或失败状态
- fulfilled:成功状态
- rejected:失败状态
简单使用promise
- 使用promise实现异步调用和链式调用
let p = new Promise((resolve,reject)=> {
resolve('成功') // 成功的执行 then执行
// reject('失败') // 失败的执行 catch执行
})
console.log(p);
p.then((res) => {
console.log(res); // 成功
return '下一次执行then'
}).then(res => {
console.log(res); // 下一次执行then
}).chatch(err => {
console.log(err)
})
then执行的时候,实现链式调用时,需要return出当前的需要的结果,会把当前return出的结果当作promise的链式调用的下一个then的回调函数的参数
输出的的结果:
// promise的实例
Promise {<fulfilled>: 'promise的实例'}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[PromiseResult]]: "promise的实例"
手写promise
定义promise
使用promise
知道,实例上的有PromiseState表示promise的状态,PromiseResult表示promise的实例返回的结果,回调函数具备两个参数resolve和reject,两个参数均为函数。
function myPromise(fn) {
this.PromiseState = 'pending' // 定义初始状态
this.PromiseResult = undefined
var resolve = function() {
}
var reject = function() {
}
if(fn) {
fn(resolve,reject)
}
}
var p = new myPromise()
console.log(p);
- promise的只能输出一个结果,是then或者是catch
- 定义两次输出状态和结果
var _this = this // 保存this的指向,使它始终指向这个函数本身
var resolve = function (val) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'fulfilled' // 如果直接调用this,this指向window
_this.PromiseResult = val
}
}
var reject = function (errVal) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'rejected'
_this.PromiseResult = errVal
}
}
then方法的实现
- 使用promise时,每次调用then都会跟在这个实例方法的后面,这样可以实现then的链式调用
- then中的函数也是一个回调函数,所以需要定义这个回调函数
this.thenCallback = undefined // 定义一个函数。用来注册then中的callback
var resolve = function (val) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'fulfilled' // 如果直接调用this,this指向window
_this.PromiseResult = val
// 为什么变成异步执行(先执行then中的函数,给thenCallback赋值,异步执行,再返回执行这)
setTimeout(function () {
if (_this.thenCallback) {
_this.thenCallback(value)
}
})
}
}
myPromise.prototype.then = function(callback) {
this.thenCallback = function (value) { // 现在的this指向的是myPromise实例
callback(value)
}
}
实现then的链式调用
- then可以不停的then下去,实现链式调用
myPromise.prototype.then = function(callback) {
var _this = this
// 链式调用,再次调用这个myPromise方法
return new myPromise(function(resolve,reject) {
_this.thenCallback = function (value) { // 现在的this指向的是myPromise实例
var res = callback(value)
resovle(res)
}
})
}
实现catch方法
- catch是直接结果为错误,只执行一次,寻找错误执行结果
// 定义一个函数对象,用来注册catch中的callback
this.catchCallback = undefined
var reject = function (errVal) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'rejected'
_this.PromiseResult = errVal
setTimeout(function () { // 为什么变成异步执行(先执行then中的函数,给catchCallback赋值,异步执行,再返回执行这)
if (_this.catchCallback) {
_this.catchCallback(errVal)
} else if (_this.thenCallback) {
_this.thenCallback(errVal)
}
})
}
}
myPromise.prototype.catch = function (callback) {
var _this = this
return new myPromise(function (resovle, reject) {
_this.catchCallback = function (errVal) { // 现在的this指向的是myPromise实例
var res = callback(errVal)
reject(res)
}
})
}
全部代码
function myPromise(fn) {
this.PromiseState = 'pending'
this.PromiseResult = undefined
var _this = this
this.thenCallback = undefined
this.catchCallback = undefined
var resolve = function (val) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'fulfilled'
_this.PromiseResult = val
setTimeout(function () { // 为什么变成异步执行(先执行then中的函数,给thenCallback赋值,异步执行,再返回执行这)
if (_this.thenCallback) {
_this.thenCallback(val)
}
})
}
}
var reject = function (errVal) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'rejected'
_this.PromiseResult = errVal
setTimeout(function () {
if (_this.catchCallback) {
_this.catchCallback(errVal)
} else if (_this.thenCallback) {
_this.thenCallback(errVal)
}
})
}
}
if (fn) {
fn(resolve, reject)
}
}
myPromise.prototype.then = function (callback) {
var _this = this
return new myPromise(function (resolve, reject) {
_this.thenCallback = function (value) { // 现在的this指向的是myPromise实例
// 回调的函数promise的状态为rejected
if (_this.PromiseState === 'rejected') {
reject(value)
} else {
var res = callback(value)
resolve(res)
}
}
})
}
myPromise.prototype.catch = function (callback) {
var _this = this
return new myPromise(function (resovle, reject) {
_this.catchCallback = function (errVal) { // 现在的this指向的是myPromise实例
var res = callback(errVal)
reject(res)
}
})
}
var p = new myPromise(function (resolve, reject) {
// resolve('then执行')
reject('catch执行')
})
console.log(p);
p.then(function (res) {
console.log(res);
return 111
}).then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
})
链式调用的问题
进行链式调用,下一个then的回调函数的参数需要上一个return出去才能拿到,否则回报
underfined
// promise
let p = new Promise((resolve,reject)=> {
resolve('1')
})
p.then(res => {
console.log(res);
return new Promise((resolve,reject)=> {
resolve('2')
})
// return '2' //两次的结果只可以
}).then(res => {
console.log(res); // 2
})
- 在手写的这个myPromise中,可以直接return获取,不可以重新把他实例化
var p = new myPromise(function (resolve, reject) {
resolve('then执行')
// reject('catch执行')
})
console.log(p);
p.then(function (res) {
console.log(res);
return new myPromise(function (resolve, reject) {
resolve('then执')
// reject('catch执行')
}) // 获取到的时这个实例化对象
// return 111 // 可以直接获取到111
}).then(function (res) {
console.log(res);
}).catch(function (err) {
console.log(err);
})
可以简写的形式使用
myPromise.resolve()
的调用
// 改造代码
var resolve = function (val) {
if (_this.PromiseState = 'pending') {
_this.PromiseState = 'fulfilled'
_this.PromiseResult = val
if (val instanceof myPromise) {
val.then(function (res) {
setTimeout(function () {
if (_this.thenCallback) {
_this.thenCallback(res)
}
})
})
} else {
setTimeout(function () {
if (_this.thenCallback) {
_this.thenCallback(val)
}
})
}
}
}
myPromise.resolve = function (res) {
return new myPromise(function (resolve, reject) {
resolve(res)
})
}
var p = new myPromise(function (resolve, reject) {
resolve('then执行')
// reject('catch执行')
})
console.log(p);
p.then(function (res) {
console.log(res);
// return 'then执行2'
return myPromise.resolve('then执行2')
}).then(function (res) {
console.log(res); // then执行2
}).catch(function (err) {
console.log(err);
})
promise还有好多东西,比如说链式调用的中断
、all
、race
等等,这些功能的实现都没有写,只完成了一个最简单的then、catch和then的链式调用。
这是本人第一次写博客,也许会有没说明白的地方,和一些错误的地方,也希望大家也可以指点出来。