我们先用Promise实现一个简单的功能,输入一个数字n,n秒后打印这个n,代码如下:
let logn = function(n) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(n)
}, n * 1000)
})
}
logn(1).then(res => {
console.log(res)
})
分析下代码结构,不难发现:
1:Promise是一个构造函数,它接收一个函数fn作为入参
2:fn有两个参数:回调函数resolve、回调函数reject,resolve接收成功后的数据
3:Promise的实例有个then方法,这个方法接收一个回调函数cb
我们初步判断Promie函数大概结构如下:
// MyPromise是构造函数,所以要大写开头
let MyPromise = function(fn) {// 接收一个fn作为参数
// 定义一下fn的回调函数resolve,resolve接收success信息
let resolve = function(res) {
}
// 定义一下fn的回调函数reject,reject接收err信息
let reject = function(err) {
}
// 给实例添加一个then方法,且这个方法接收一个回调函数cb
this.then = function(cb) {
}
}
接下来分析下几个函数是怎么跑的,经过仔细分析得出如下结论:
// 5个函数执行顺序如下
1:new Promise(fn) // 实例化logn
2:fn(resolve, reject) // 设置setTimeout
3:then(cb) // 接收成功回调cb
4:resolve(res) or reject(err) // 调用cb
更新一下MyPromise:
let MyPromise = function(fn) {
// 1、先实例化logn
let resolve = function(res) {
// 4、执行成功的回调函数cb,并把res传递进去
this.success(res)
}
let reject = function(err) {
}
this.then = function(cb) {
// 3、接收成功的回调函数cb
this.success = cb
}
// 2、执行fn,设置setTimeout
fn(resolve, reject)
}
我们把Promise换成MyPromise试一下:
let logn = function(n) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(n)
}, n * 1000)
})
}
logn(1).then(res => {
console.log(res)
})
执行代码发现控制台报错了:this.success is not a function。因为resolve是定时器中的函数,this默认指向window。所以修改下代码,给resolve函数bind一下this,并执行下MyPromise,发现1秒后打印了1
let MyPromise = function(fn) {
let resolve = function(res) {
this.success(res)
}
let reject = function(err) {
}
this.then = function(cb) {
this.success = cb
}
fn(resolve.bind(this), reject.bind(this))
}
let logn = function(n) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve(n)
}, n * 1000)
})
}
logn(1).then(res => {
console.log(res)
})
我们发现MyPromise只处理了resolve函数,没有处理reject函数。为了测试reject,所以我们改变一下需求,传一个0 - 10之间的随机整数n,如果n小于5,1秒后打印'成功',否则打印'失败':
let MyPromise = function(fn) {
let resolve = function(res) {
this.success(res)
}
// copy一下resolve
let reject = function(err) {
this.error(err)
}
this.then = function(cb) {
this.success = cb
}
// copy一下this.then
this.catch = function(cb) {
this.error = cb
}
fn(resolve.bind(this), reject.bind(this))
}
let logn = function(n) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
if(n < 5) {
resolve('成功')
}else{
reject('失败')
}
}, 1000)
})
}
let n = (Math.random() * 10).toFixed(0)
logn(n).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
执行发现又报错了:Cannot read property 'catch' of undefined。因为then和catch都没有return数据,联系到函数的链式编程,我们加一个return this,再执行一下,发现成功实现了catch:
let MyPromise = function(fn) {
let resolve = function(res) {
this.success(res)
}
let reject = function(err) {
this.error(err)
}
this.then = function(cb) {
this.success = cb
return this
}
this.catch = function(cb) {
this.error = cb
return this
}
fn(resolve.bind(this), reject.bind(this))
}
let logn = function(n) {
return new MyPromise((resolve, reject) => {
setTimeout(() => {
if(n < 5) {
resolve('成功')
}else{
reject('失败')
}
}, 1000)
})
}
let n = (Math.random() * 10).toFixed(0)
logn(n).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
})
以上就是我在写promise的时候遇到的问题和个人思考,欢迎小伙伴留言评论
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!