Hibop.github.io
Hibop.github.io copied to clipboard
关于异步——promise
异步操作:
- IO
- ajax请求
- 计时器:setTimeout、setInterval
Promise挂载的方法
-
静态方法:Static Method
- Promise.all()
- Promise.race()
- Promise.resolve()
- Promise.reject()
-
实例方法:
- Promise.protype.then(resoleve, reject)
- Promise.protype.catch()
- Promise.protype.finally()
-
构造方法:constructor
var promise = new Promise((resolve, reject) => {
resolve(data); // 返回成功data给then;
reject(error); // 返回失败error给catch
})
三种状态
- pending
- resolve
- reject 【注意】 没有像ajax那样的50% pending 30%pending
并发Promise
- Promise.all
- Promise.race
串行Promise
- Promise.then
- Promise.catch
几个等价用法
- Promise.resolve('foo') new Promise(resolve => resolve('foo'))
- var p = Promise.reject('出错了') new Promise((resolve, reject) => reject('出错了'))
- p.then(null, err => console.log(err)) p.then(null).catch(err => console.log(err))
then(resolveHandler, rejectHandler)中的rejectHandler不会捕获resolveHandler中的错误, 只会捕获then前面的错误, 而catch是捕获整个链路的错误,故推荐使用catch
promise穿透现象
then(fn) fn如果返回才可以传递到下一个then, 否则fn不为函数或者返回null undefined 下一个then会接收上一个的return值
Promise.resolve('foo').then(Promise.resolve('bar')).then(function (result) {
console.log(result); // 'foo' 不是‘bar’
});
promise链式调用: 调用队列实现
Promise.resolve().then(fetch1).then(fetch1);
可以使用更优雅的函数式方式
[fetch1, fetch1].reduce((p, f) => p.then(f), Promise.resolve())
或者更加函数话封装成函数
let composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));
通过composition pipeline传入的初始值(可以为同步或者异步),保证顺序执行
let transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2);
transformData(data);
ECMAScript 2017标准中, 串行组合可以通过使用async/await而变得更简单:
for (let f of [func1, func2]) {
await f();
}
async await
- TODO
最后来个小测试巩固下
console.log('0.outer');
// setTimeout有个最小执行时间(minimum delay of 4ms ),并不是0s执行的
setTimeout(() => {
console.log('1.setTimeout')
}, 0);
new Promise((resolve, reject) => {
console.log('2.promise before resolve');
for(var i=0; i < 10000; i++) {
if(i === 10) {console.log('3.promise')}
i === 9999 && resolve();
}
console.log('4.promise after resolve');
}).then(() => {
console.log('5.then');
}).then(() => {
throw new Error('Something failed');
console.log('5.1.then error');
}).then(() => {
console.log('5.2.then after error');
}).catch(() => {
console.log('5.3. catch');
}).then(() => {
console.log('5.4. after catch then');
}).finally(() => {
console.log('5.5. finally');
})
console.log('6.outer');
- [x] async function: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/async_function
- [ ] AsyncFunction: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction
- [ ] async function expression: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/async%E5%85%81%E8%AE%B8%E5%A3%B0%E6%98%8E%E4%B8%80%E4%B8%AA%E5%87%BD%E6%95%B0%E4%B8%BA%E4%B8%80%E4%B8%AA%E5%8C%85%E5%90%AB%E5%BC%82%E6%AD%A5%E6%93%8D%E4%BD%9C%E7%9A%84%E5%87%BD%E6%95%B0
常见问题汇总
- 异步顺序
const promise = new Promise((resolve, reject) => {
console.log(1);
resolve();
console.log(2);
});
promise.then(() => {
console.log(3);
});
console.log(4);
result: 1,2,4,3
- Promise状态一旦改变,无法在发生变更
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
reject('error')
}, 1000)
})
promise.then((res)=>{
console.log(res)
},(err)=>{
console.log(err)
})
reslut: success
- 传值穿透
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log)
result: 1
- 先微任务后宏任务
setTimeout(()=>{
console.log('setTimeout')
})
let p1 = new Promise((resolve)=>{
console.log('Promise1')
resolve('Promise2')
})
p1.then((res)=>{
console.log(res)
})
console.log(1)
result: Promise1 1 Promise2 setTimeout