声明,只是简单地提了提promise的基本使用,大牛绕道^_^
1.先看一个例子
你需要知道1.axios是个库
2.axios()返回一个Promise实例
3.你可以把axios()理解为$.ajax(),它们功能相近,只不过axios遵循promise规范
axios({
url: '.'
}).then((resolve) => {
console.log(resolve)
return '我是第二个then'
}, (reject) => {
console.log(reject)
}).then((resolve_2) => {
console.log(resolve_2) // '我是第二个then'
}, (reject_2) => {
console.log(reject_2)
})
为了防止你对这个链式调用
看得眼花缭乱,我把这个给简化一下
axios({
url: '.'
}).then(成功回调, 失败回调)
.then(成功回调2, 失败回调2)
ok,准备好了吗?下面我们先来了解Promise的一些基本概念
2.Promise的基本概念
2.1Promise的作用
Promise是专门用来解决异步编程问题的,避免了层层嵌套的回调函数[Callback Hell]
下面是一个用传统方法Callback Hell来写的异步代码
可以非常明显地看出来,Callback Hell的方式让代码的可读性变得非常差
function loadImg(src, callback, fail) {
let img = new Image()
img.onload = function () {
// 成功回调
callback(img)
}
img.onerror = fail // 失败回调
img.src = src
}
let src = 'https://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png'
loadImg(src, function (img) {
console.log(img.width)
}, function () {
console.log('error')
})
2.2 Promise的三个状态
-
pending
初始态,既不成功也不失败 -
fulfilled
异步操作成功 -
rejected
异步操作失败
Promise对象代表一个异步操作,且只有异步操作的结果,可以决定当前是哪一种状态
,任何其他操作都无法改变这个状态,peding可转化为fulfilled与rejected,但fulfilled与rejected不可相互转化
那知道这三个状态又有什么用咧?
OK,我们看下面的代码
axios({
url: '.'
}).then(成功回调, 失败回调)
axios({url: '.'})
异步操作成功代表了pending
-> fulfilled
-> then里的第一个参数
【成功回调】
异步操作失败代表了pending
-> rejected
-> then里的第二个参数
【失败回调】
3.then和catch的链式调用
因为 Promise.prototype.then
和 Promise.prototype.catch
方法返回promise 对象
所以它们可以被链式调用。
OK,下面让我们仔细看一下回调触发机制究竟怎样的过程
axios({
url: '.'
}).then(成功回调, 失败回调)
.then(成功回调2, 失败回调2)
是不是看的有点晕?没关系,下面我来详细解释一下
1.异步操作成功
-> 进入第一个then的成功回调
-> 成功回调
执行异步操作成功 -> 由于又返回了一个Promise实例,其状态由于异步操作成功,由pending
转为了fullfiled
,所以还可以再调用第二个then -> 进入第二个then的成功回调2
2.异步操作失败
-> 进入第一个then的失败回调
-> 失败回调
执行异步操作成功 -> 由于又返回了一个Promise实例,其状态由于异步操作成功,由pending
转为了fullfiled
,所以还可以再调用第二个then -> 进入第二个then的成功回调2
你的问题:
1.为什么第一个then不论调用成功回调
还是失败回调
,第二个then都会调用成功回调2
呢
答:因为第二个then调用进入哪个回调函数,完全是看第一个then返回的Promise是什么状态,换言之 —— 看异步操作成功与否
举一个栗子
axios({
url: '.'
}).then((resolve) => {
return xxx
// 注意xxx是个未声明的变量
// 浏览器会报错,说明异步操作失败了
// 所以第一个then返回的Promise的状态是 rejected
}, (reject) => {})
.then((resolve_2) => {
console.log(1)
}, (reject_2) => {
// 所以第二个then只会调用它的第二个参数
console.log(2)
})
2.你咋不提catch咧?
因为catch就是then的一个语法糖呀
catch等价于then只有第二个参数【失败回调】的形式
上面的例子用catch,可以这么写
axios({
url: '.'
}).then((fulfilled) => {
return xxx
// 注意xxx是个未声明的变量
// 所以第一个then返回的Promise的状态是 rejected
}, (rejected) => {
}).catch((rejected) => {
// 所以直接进入catch
console.log(2)
})
4.自己写一个Promise
第一步
// 声明一个函数 让这个函数返回一个Promise实例
let setPromise = function () {
return new Promise()
}
第二步
// new Promise()接受一个函数
// 规定这个函数必须要有两个参数【成功回调,失败回调】
let a = 0
let setPromise = function () {
let fn = (x, y) => {
setTimeout(() => {
x('success')
// 一定要写上异步操作成功后,会调用的回调函数
}, 2000)
}
return new Promise(fn)
// 在new的过程中一定有一句fn.call(undefined, fulfilled, rejected)
}
第三步
// 写的更装逼点,顺别把x,y换个名字【其实是规定】
let setPromise = function () {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
}, 2000)
}) // 在new的过程中一定有一句fn.call(undefined, fulfilled, rejected)
}
第四步
// 你要做什么,就用then输入到这个Promise实例里面去
let promiseInstance = setPromise()
promiseInstance.then((success) => {
console.log(success) // 'success'
}, () => {
console.log('失败啦')
})
总结
let setPromise = function () {
return new Promise((resolve, reject) => {
// 你的异步代码
setTimeout(() => {
resolve('success') // 给成功回调resolve传递一个参数 'success'
console.log('测试一下') // 两秒之后被执行
}, 2000)
})
}
// 你要做什么,就用then输入到这个Promise实例里面去
let promiseInstance = setPromise()
promiseInstance.then((resolve) => {
// 异步操作执行成功后执行
console.log(resolve) // 'success'
console.log('完美运行') // '完美运行'
}, () => {
console.log('失败啦')
})
5.最后
其实对于Promise和then有一个更具象化的理解
Promise的中文翻译是承诺
,then的中文翻译是然后
所以,你可以想象你去买橘子,结果店里没有进货,店员对你Promise
,只要他店里到货,then
他就会通知你