三个点语法
Promise
https://wenku.baidu.com/view/21601c09ccc789eb172ded630b1c59eef8c79ad5.html
https://www.jianshu.com/p/fe5f173276bd
https://www.cnblogs.com/xinggood/p/11836096.html
问题的提出:解决回调套回调的回调地狱。ES6
名字来源 : “君子一诺千金,承诺的事情一定会去执行”
promise的使用场景
使用promise能够有效的解决js异步回调地狱问题
能够将业务逻辑与数据处理分隔开使代码更优雅,方便阅读,更有利于代码维护。Promise对象提供统一的接口,使得控制异步操作更加容易。
特点
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
注意,为了行文方便,本章后面的resolved统一只指fulfilled状态,不包含rejected状态。
基本用法
function promiseTest(r) {
//这里的resolve和reject 是Promise对象预先设置好的形参 名字可以改成其他的 只和顺序有关
let promise = new Promise(function(resolve, reject){
if (r % 2 == 0) {
resolve('成功') //即写逻辑规定什么时候调用resolve方法 代表流程正常
} else {
reject('失败')
}
})
return promise
}
const promise = promiseTest()
promise.then(function(data){
console.log(data)
}).catch(function(err){
console.log(err)
})
上面的代码很难理解 所以需要结合源码怎么实现的来帮助理解
// 手写promise源码,这里为简化版本 去掉了异步的 帮助理解
// 定义我们自己的Promise类
class Mypromise {
//执行一个构造器 executor的实际含义是选择谁执行
//由于它在下面的使用中executor(resolve, reject) 有两个参数 所以我们在传参的时候 也要写两个参数
constructor(executor) {
this.state = 'pending' //状态值
this.value = undefined //成功的返回值
this.reason = undefined //失败的返回值
// 成功 这里的resolve是executor的形参!指定一个函数
let resolve = (value) => {
if (this.state == 'pending') {
this.state = 'fullFilled'
this.value = value
}
}
// 失败
let reject = (reason) => {
if (this.state == 'pending') {
this.state = 'rejected'
this.reason = reason
}
}
try {
// 带括号的,立即执行函数 这里执行的是我们传入的东西
executor(resolve, reject)
} catch (err) {
// 失败则直接执行reject函数
reject(err)
}
}
then(onFullFilled, onRejected) {
// 状态为fulfuilled,执行onFullFilled,传入成功的值
if (this.state == 'fullFilled') {
onFullFilled(this.value)
}
// 状态为rejected,执行onRejected,传入失败的值
if (this.state == 'rejected') {
onRejected(this.reason)
}
}
}
const p = new Mypromise((resolve, reject) => {
// resolve('success') // 走了成功就不会走失败了
throw new Error('失败') // 失败了就走resolve
reject('failed') // 走了失败就不会走成功
})
p.then((res) => {
console.log(res)
}, (err) => {
console.log(err)
})
所以,resolve和rejecct的实际作用是改变状态!以执行then!
Promise说得通俗一点就是一种写代码的方式。
//传统的多重回调 像一个金字塔 而且不好阅读 这里还没考虑fail的情况
getData1(data1 => {
getData2(data1, data2 => {
getData3(data2, data3 => {
getData4(data3, data4 => {
getData5(data4, data5 => {
// 终于取到data5了
})
})
})
})
})
// 如果用promise改写,这样的代码,是线性的,符合人的阅读习惯,代码表示的流程清晰,便于阅读
getData1()
.then(getData2)
.then(getData3)
.then(getData4)
.then(getData5)
.then(data => {
// 取到最终data了
})
//异步代码并行
有了多个异步任务后,下面假设想要多个异步任务并行执行,获取执行成功后,才处理结果。用回调方式来写,可采用下面的办法:
let tasks = [getData1, getData2, getData3, getData4, getData5]
let datas = []
tasks.forEach(task => {
task(data => {
datas.push(data)
if (datas.length == tasks.length) {
// datas里已经包含全部的数据了
}
})
})
上面结合数组,使用了forEach方法来为每个任务传入回调。如果改用promise来实现,代码会是这样:
// 先要把getData们转成promise对象
// 然后
Promise.all([
getData1,
getData2,
getData3,
getData4,
getData5
]).then(datas => {
// 已拿到全部的data,可以处理了
})