Promise
出现目的,为了解决回调地狱
promise的用法就不赘述了,提一下错误处理吧
ajax('/api/users11.json')
.then(function onFulfilled (value) {
console.log('onFulfilled', value)
}, function onRejected (error) {
console.log('onRejected', error
})
// 使用 catch 注册失败回调是更常见的
ajax('/api/users11.json')
.then(function onFulfilled (value) {
console.log('onFulfilled', value)
})
.catch(function onRejected (error) {
console.log('onRejected', error)
})
then的第二个参数就是reject时执行函数
在promise中手动调用reject()会打印“onRejected”,代码发生错误也会触发打印“onRejected”。
然后catch = then的第二个参数(失败回调函数)
他俩的区别是catch能抓到整个链路的错误,then中的错误处理函数只能抓到他之前的promise中的错误
实现几个例子
let promise = new Promise((resolve, reject) => {
reject(2000)
})
promise
.then((v)=>console.log('then1成功', v), (r)=>console.log('then1失败', r))
.catch((e)=>console.log('catch1', e))
.then((v)=>console.log('then2成功', v), (r)=>console.log('then2失败', r))
.catch((e)=>console.log('catch2', e))
// =>then1成功 1000
// =>then2成功 undefined 因为then1中没有return v
let promise = new Promise((resolve, reject) => {
reject(2000)
})
promise
.then((v)=>console.log('then1成功', v), (r)=>{console.log('then1失败', r); return r})
.catch((e)=>console.log('catch1', e))
.then((v)=>console.log('then2成功', v), (r)=>console.log('then2失败', r))
.catch((e)=>console.log('catch2', e))
// =>then1失败 2000
// =>then2成功 2000
// 可见错误处理一回后,后面的catch也不会走到
// 错误处理函数结束后,后续继续走成功回调
let promise = new Promise((resolve, reject) => {
reject(2000)
})
promise
.catch((e)=>console.log('catch0', e))
.then((v)=>console.log('then1成功', v), (r)=>console.log('then1失败', r))
.catch((e)=>console.log('catch2', e))
// => catch0 2000
// => then1成功 2000
// 还是错误处理只处理过一回后,将不再走以后的错误处理
// 除非后面又有新的错误
Generator
Promise的异步方案还是不够扁平化,所以出现了Generator生成器函数
// Generator 配合 Promise 的异步方案
function ajax (url) {
return new Promise((resolve, reject) => {
var xhr = new XMLHttpRequest()
xhr.open('GET', url)
xhr.responseType = 'json'
xhr.onload = () => {
if (xhr.status === 200) {
resolve(xhr.response)
} else {
reject(new Error(xhr.statusText))
}
}
xhr.send()
})
}
function * main () { // *生成器函数
try {
const users = yield ajax('/api/users.json') // yield,暂停执行,等待生成器对象的next方法调用
console.log(users)
const posts = yield ajax('/api/posts.json')
console.log(posts)
const urls = yield ajax('/api/urls11.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
function co (generator) {
const g = generator()
function handleResult (result) {
if (result.done) return // 生成器函数结束
result.value.then(data => {
handleResult(g.next(data))
}, error => {
g.throw(error)
})
}
handleResult(g.next())
}
co(main)
Async Await
Async完全就是上面代码方案的语法糖,把*变成Async,yield变成await,并且不需要co函数了
async function main () {
try {
const users = await ajax('/api/users.json')
console.log(users)
const posts = await ajax('/api/posts.json')
console.log(posts)
const urls = await ajax('/api/urls.json')
console.log(urls)
} catch (e) {
console.log(e)
}
}
同步的方式写异步,舒服了。