// 第一题 1 3
Promise.resolve().then(() => {
console.log(1)
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)
})
// 第二题 1 2 3
Promise.resolve().then(() => {
console.log(1)
throw new Error('error1')
}).catch(() => {
console.log(2)
}).then(() => {
console.log(3)
})
// 第三题 1 2
Promise.resolve().then(() => {
console.log(1)
throw new Error('error1')
}).catch(() => {
console.log(2)
}).catch(() => {
console.log(3)
})
// 第一题
async function fn() {
return 100
}
(function() {
const a = fn() // ?? promise pending
const b = await fn() // ?? promise resolved 100
})();
// 第二题,分别打印出什么
// start 100 200 error:uncaught(in promsie) 300
!(async function() {
console.log('start')
const a = await 100
console.log('a', a)
const b = await Promise.resolve(200)
console.log('b', b)
const c = await Promise.reject(300)
console.log('c', c)
console.log('end')
})();
// 100 400 300 200
console.log(100)
setTimeout(() => {
console.log(200)
})
Promise.resolve().then(() => {
console.log(300)
})
console.log(400)
// script start
// async1 start
// async2
// promise1
// script end
// async1 end
// promise2
// setTimeout
async function async1(){
console.log('async1 start')
await async2()
// 下面的代码相当于回调,所以先会去执行同步代码,当同步代码执行完之后会再执行下一行的代码
console.log('async1 end')
}
async function async2(){
console.log('async2')
}
console.log('script start')
// 宏任务最后执行,所以晚于promise then这个微任务的执行
setTimeout(() => {
console.log('setTimeout')
})
async1()
new Promise(resolve => {
console.log('promise1')
resolve()
}).then(() => {
console.log('promise2')
})
console.log('script end')
js如何执行?
异步代码执行?
const LOOP_MAX_COUNT = 10000
for (let index = 0; index < LOOP_MAX_COUNT; index++) {
console.log(index);
}
// 这个定时器的执行也需要同步代码执行完之后才会执行,
// 即当同步代码执行完之后,这个定时器才会被移到callback queue,之后才会被event loop添加到call stack执行
setTimeout(function () {
console.log('timeout')
}, 300)
dom事件和event loop的关系:
代码执行到dom事件时,会首先记录下这个回调,将其存储下来,当用户触发了该事件时,会将存储下来的回调函数放到call stack去执行。但注意dom事件不是异步,只是基于event loop实现的
注意:任何基于回调的代码,包括dom事件、定时器、网络请求,都是基于event loop的
then正常返回resolved,里面报错则返回rejected
catch正常返回resolved,里面报错则返回rejected(catch实质是then的第二个回调函数)
举个例子:
const p1 = Promise.resolve().then(_ => 100); // resolved
const p2 = Promise.reject().catch(_ => 100); // resolved
const p3 = Promise.resolve().then(() => { throw new Error('something goes wrong') }); // rejected
const p4 = Promise.reject().catch(() => { throw new Error('something goes wrong') }); // rejected
async/await是同步语法,彻底消灭了回调函数。举个例子:
// 如下的打印顺序是start 2s之后 async/await end
!(async () => {
console.log('start')
const res = await new Promise((resolve) => {
setTimeout(() => {
resolve('async/await')
}, 2000)
});
console.log(res)
console.log('end')
})()
async/await是Promise的语法糖,执行async函数,返回的是Promise对象,await相当于promise的then,await必须要用try catch捕获异常,代替了Promise的catch
async function fn1() {
return 100
}
const res = fn1();
res.then(data => console.log(data)) // 100
async function async1() {
console.log('async1 start') // 2
await async2() // 先执行async2(),然后await,后面的代码都可以看成是一个callback里的内容,即异步
// 类似event loop
// 这个时候后面的代码会被添加到callback queue等待被调用(同步代码执行玩之后调用)
console.log('async 1 end'); // 5
}
async function async2() {
console.log('async2'); // 3
}
console.log('script start'); // 1
async1()
console.log('script end'); // 4
function mutilple(num) {
return new Promise(resolve => {
setTimeout(() => {
resolve(num * num)
}, 1000);
})
}
const nums = [1, 2, 3]
!(async () => {
for (const num of nums) {
const res = await mutilple(num);
console.log(res)
}
})()
console.log(100);
// 宏任务
setTimeout(() => {
console.log(200);
});
// 微任务
setTimeout(() => {
console.log(201);
});
Promise.resolve().then(() => console.log(300));
console.log(400)
const p1 = document.createElement('p');
const container = document.querySelector('.container')
p1.innerText = '一段文字';
const p2 = p1.cloneNode(true);
const p3 = p1.cloneNode(true);
container.appendChild(p1)
container.appendChild(p2)
container.appendChild(p3)
// 同步代码完成,dom即将渲染
Promise.resolve().then(() => {
console.log('length1', container.childElementCount)
// 这个时候dom还未渲染
alert('Promise then')
});
setTimeout(() => {
console.log('length2', container.childElementCount)
// 这个时候dom已经渲染完成
alert('timeout')
});
准确来说event loop执行过程是:在执行代码时,遇到异步代码先将回调放在异步队列,将promise、async/await等ES规范的微任务放进异步队列中的微任务队列;而将定时器、dom事件回调、网络请求等w3c规范的异步任务放到web APIs,等到一定时机的时候将其放入宏任务队列,当同步代码执行完之后,先执行当前的微任务,尝试DOM渲染,再执行当前的宏任务,等完成之后再进行event loop。用顺序表示为: