Promise练习题
const promise = new Promise((resolve,reject)=>{
console.log(1)
resolve()
console.log(2)
})
promise.then(()=>{
console.log(3)
})
console.log(4)
依次输出1243,不做过多解释,因为比较简单
const promise = new Promise((resolve,reject)=>{
console.log(1)
console.log(2)
})
promise.then(()=>{
console.log(3)
})
console.log(4)
去掉上面第三行的代码,意思就是我们没有把Promise的状态推向到已决状态,所以只会输出 1 2 4
let p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('success')
},1000)
})
let p2 = p1.then(()=>{
throw new Error('error!!!')
})
console.log('promise1',p1)
console.log('promise2',p2)
setTimeout(()=>{
console.log('promise1',p1)
console.log('promise2',p2)
},2000)
这里的p2是由于p1.then返回的一个全新的promise,他的状态是由p1决定的,当一开始输出的时候p1和p2都是等待着状态,在一秒后,p1变为成功状态,并且p1.then((resolve,reject)),就执行resolve函数,将p2的状态改为拒绝
let p = new Promise((resolve,reject)=>{
resolve('success1')
reject('error')
resolve('success2')
})
p.then((res)=>{
console.log('then:',res)
})
输出:then:success1
这里很好理解,一旦从pending态到resolved或者reject是不可更改的,并且也是不可逆的
Promise.resolve(1).then((res)=>{
console.log(res)
return 2
}).catch((err)=>{
return 3
}).then((res)=>{
console.log(res)
})
这里输出1 2
Promise.resolve()是将当前的Promise的状态更改为成功,并且传递值,所以下一个then中可以接受到这个值,并且输出。
之后的then中return就相当于返回了一个新的Promise,并且携带需要传递的参数,实现链式调用
let p = new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log('once')
resolve('success')
},1000)
})
let start = Date.now()
p.then((res)=>{
console.log(res,Date.now()-start)
})
p.then((res)=>{
console.log(res,Date.now()-start)
})
输出
once
success 1001
success 1002
一秒之后,promise的状态更改,promise.then()可以调用多次,同时所有的then都能获取带res的值,并且输出
Promise.resolve().then(()=>{
return new Error('error!!!')
}).then((res)=>{
console.log('then:',res)
}).catch((err)=>{
console.log('catch:',err)
})
输出:then: Error: error!!!
then
中就算抛出一个error对象也不会影响Promise的状态,返回任意一个非 promise 的值都会被包裹成 promise 对象,即 return new Error(‘error!!!’) 等价于 return Promise.resolve(new Error('error!!!'))
Promise.resolve(1)
.then(2)
.then(Promise.resolve(3))
.then(console.log())
这里then内部期望传入函数,如果 不是函数,就发生值穿透,最后console.log
是输出的1
const first = () => (new Promise((resolve, reject) => {
console.log(3);
let p = new Promise((resolve, reject) => {
console.log(7);
setTimeout(() => {
console.log(5);
resolve(6);
}, 0)
resolve(1);
});
resolve(2);
p.then((arg) => {
console.log(arg);
});
}));
first().then((arg) => {
console.log(arg);
});
console.log(4);
输出:3 7 4 1 2 5
第一轮事件循环,先执行宏任务,主script,new Promise立即执行,输出 3,执行p这个new Promise操作,输出 7,发现setTimeout,将回调函数放入下一轮任务队列(Event Quene),p的then,暂且命名为then1,放入微任务队列,且first也有then,命名为then2,放入微任务队列。执行console.log(4),输出 4,宏任务执行结束。
再执行微任务,执行then1,输出 1,执行then2,输出 2
第一轮事件循环结束,开始执行第二轮。第二轮事件循环先执行宏任务里面的,也就是setTimeout的回调,输出 5.resolve(6)不会生效,因为p的Promise状态一旦改变就不会再变化了。
process.nextTick(() => {
console.log('nextTick')
})
Promise.resolve()
.then(() => {
console.log('then')
})
setImmediate(() => {
console.log('setImmediate')
})
console.log('end')
process.nextTick 和 promise.then 都属于 microtask,而 setImmediate 属于 macrotask,在事件循环的 check 阶段执行。事件循环的每个阶段(macrotask)之间都会执行 microtask,事件循环的开始会先执行一次 microtask。
var a;
var b = new Promise((resolve, reject) => {
console.log('promise1');
resolve();
}).then(() => {
console.log('promise2');
}).then(() => {
console.log('promise3');
}).then(() => {
console.log('promise4');
});
a = new Promise(async (resolve, reject) => {
console.log(a);
await b;
console.log(a);
console.log('after1');
await a
resolve(true);
console.log('after2');
});
console.log('end');
输出:
promise1
undefined
end
promise2
promise3
promise4
Promise { }
after1
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout