Promise对异步状态进行管理
Promise
是一种异步任务顺序执行的新方法,为了解决callback问题。对异步状态进行管理。
基础语法
var promise = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
console.log("我叫张晓龙");
resolve()
}, 3000)
})
}
promise().then(() => {
console.log("好的知道了")
})
Promise
一共有三种状态,且成功和失败的状态时不可逆的
new Promise()会立即执行,所以一般在使用new Promise执行函数时,需要放到一个函数中去,并return出来,这样才能更好的执行。
new Promise()共有两个参数,一个是resolve,是函数体内代码成功执行后执行执行的回调函数。另一个是reject,是函数体中的代码,执行失败之后执行的回调函数。
成功的回调和失败回调有两种执行方式:
-
使用.then(successBack,failBack)
promise().then(
() => { console.log("好的知道了") }, () => { console.log("听不到你说啥"); }
)
-
使用.cath
promise().then(() => {
console.log("好的知道了")
}).catch(() => {
console.log("听不到你说啥");
})
Promise的使用场景
由于Promise的出现是为了解决callback问题的,而常见的需要异步任务顺序执行的操作就是,ajax操作。
Promise的静态方法
let foo = res => {
if (res) {
return new Promise(resolve => {
resolve('成功了~~~')
})
} else {
return Promise.reject("失败了~~~")
}
}
foo(false).then(res => { console.log(res) }).catch(res => { console.log(res) })
Promise.all()和Promise.race()
// Promise.all()和Promise.race()
let p1 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p1成功了')
}, 1000)
})
let p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('p2失败了')
}, 2000)
})
let p3 = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('p3成功了')
}, 3000)
})
// Promise.all([p1, p2, p3]).then(res => {
// console.log(res);
// }).catch(res => {
// console.log(res);
// })
Promise.race([p1, p2, p3]).then(res => {
console.log(res);
}).catch(res => {
console.log(res);
})
// Promise.all()只有所有的都成功才会返回成功,只要有一个不成功,就返回不成功的那个promise
// Promise.race()会返回最先接收到的结果,先接收到成功的就代表成功了,先接收到失败的就代表失败了。
Promise中reject和catch的区别
Promise的参数的函数中有reject来处理失败情况,catch方法也可以处理失败情况,那么两种方式有什么区别呢?
reject
-
是Promise的静态方法
-
对应then中第二个参数,如果then中没有写第二个回调,则进入catch
-
只能捕获到Promise对象中函数的错误
-
可以将promise 的状态改为 rejected
catch
-
是Promise实例的方法, 对错误信息统一管理
-
可以捕获到调用链路上的所有异常
-
断网情况进入catch
-
可以通过 reject 和 throw new error 来触发,但只有通过 reject 来触发,才能把promise状态改为rejected
new Promise()调用了Promise的构造函数,那么new Promise()的参数函数里的代码是同步执行还是异步执行呢?then方法是同步还是异步呢?
new Promise(resolve=>{
console.log(1);
resolve(3);
}).then(num=>{
console.log(num);
});
console.log(2);
//依次为 123
//promise构造函数是同步执行的,then方法是异步执行的
Generator
Generators 是可以用来控制迭代器的函数。它们可以暂停,然后在任何时候恢复。
function* generatorForLoop() {
for (let i = 0; i < 5; i += 1) {
yield console.log(i)
}
}
const genForLoop = generatorForLoop()
console.log(genForLoop.next()) // first console.log - 0
console.log(genForLoop.next()) // 1
console.log(genForLoop.next()) // 2
console.log(genForLoop.next()) // 3
console.log(genForLoop.next()) // 4
对比下代码,常规的循环只能一次遍历完所有值,Generator 可以通过调用 next 方法拿到依次遍历的值,让遍历的执行变得“可控”。
基本语法
定义
function* gen() {
yield 1
yield 2
yield 3
}
let g = gen()
这个是 Generator 的定义方法,有几个点值得注意:
-
比普通函数多一个 *
-
函数内部用 yield 来控制程序的执行的“暂停”
-
函数的返回值通过调用 next 来“恢复”程序执行
注意:
Generator 函数的定义不能使用箭头函数,否则会触发 SyntaxError 错误
yield 表达式
yield 关键字用来暂停和恢复一个生成器函数
关于 yield 表达式,要熟记几个知识点:
-
yield 表达式的返回值是 undefined,但是遍历器对象的 next 方法可以修改这个默认值。
-
yeild * 是委托给另一个遍历器对象或者可遍历对象
function* gen() { let val val = yield 1 console.log( `1:${val}` ) // 1:undefined val = yield 2 console.log( `2:${val}` ) // 2:undefined val = yield [3, 4, 5] console.log( `3:${val}` ) // 3:undefined }
Generator 对象的 next 方法,遇到 yield 就暂停,并返回一个对象,这个对象包括两个属性:value 和 done。“
应用场景
还是前面的异步操作,按顺序读取a.json、b.json、c.json,如果使用Generator该如何实现呢?
场景1
function request(url) {
ajax(url, res => {
getData.next(res)
})
}
function* gen() {
let res1 = yield request('static/a.json')
console.log(res1)
let res2 = yield request('static/b.json')
console.log(res2)
let res3 = yield request('static/c.json')
console.log(res3)
}
let getData = gen()
getData.next()
异步编程解决方案
为什么可以使用:
因为Generator中yield关键字可以让代码暂停,也可以使用.next()让代码继续执行,根据这一特性,就可以让异步任务顺序执行。
// 将发送ajax请求封装成一个方法
let ajax = (url, callback) => {
var xmlhttp = new XMLHttpRequest()
xmlhttp.open("GET", url, true)
xmlhttp.send()
xmlhttp.onreadystatechange = () => {
if (xmlhttp.readyState === 4 && xmlhttp.status === 200) {
var res = JSON.parse(xmlhttp.responseText)
callback(res)
}
}
}
// 定义一个require函数用于发送ajax请求
let require = (url) => {
ajax(url, res => {
getData.next(res)
})
}
// 使用Generator来解决异步编程
function* gen() {
let res1 = yield require('a.json')
console.log(res1)
let res2 = yield require('b.json')
console.log(res2)
let res3 = yield require('c.json')
console.log(res3)
}
let getData = gen()
getData.next()