promise 可以看作是一个对象,是异步编程的一种解决方案,可以获取异步操作的消息。
new Promise((resolve, reject) => {
console.log('Promise')
resolve(1)
})
//结果 new Promise
new Promise((resolve, reject) => {
console.log('Promise')
resolve(1)
}).then(function(value){
console.log(value); //此处then调用了resolve(1),输出结果为:Promise 1
return Promise.reject('reject'); //返回一个promise
}).then(function(value){ // 只能调用其中一个函数,此处调用了reject,输出reject:reject
console.log('resolve:' + value);
}, function(err) {
console.log('reject:' + err);
});
const p = new Promise(function(resolve,reject){
resolve(1);
}).then(function(value){ // 第一个then输出:1
console.log(value);
return value * 2;
}).then(function(value){ // 第二个then输出:2
console.log(value);
})
总体过程:启动异步任务 => 返回promie对象 => 给promise对象绑定回调函数(甚至可以在异步任务结束后指定)
优点:promise的链式结构可以解决回调地狱问题
缺点:
async可以看成promise的进阶,放在函数前面表明这是一个异步函数,会返回一个Promise对象,await必须放在async函数里面,若是放在外面会得到一个语法错误。async 函数执行时,如果遇到 await 就会先暂停执行 ,等到await后面触发的异步操作完成后,恢复 async 函数的执行并返回解析值。
let s = 0
let f = async () => {
s = s + await 10
console.log('4', s) // -> 4 10
}
f()
s++
console.log('1', s) // -> 1 1
//输出顺序:1 1 4 10
let s = 0
let f = async () => {
s = s + await 10
console.log('4', s) // -> 4 10
}
f().then(console.log('3', s))
s++
console.log('1', s) // -> 1 1
//输出顺序:3 0 1 1 4 10
使用then方法添加回调函数的情况:
async function helloAsync(){
return "Async";
}
console.log(helloAsync()) // Promise {: "Async"}
helloAsync().then(val=>{
console.log(val); // Async
})
function testAwait(){
console.log("testAwait");
}
async function helloAsync(){
await testAwait();
console.log("helloAsync");
}
helloAsync();
// testAwait
// helloAsync
function testAwait (x) {
return new Promise(resolve => {
setTimeout(() => {
resolve(x);
}, 2000);
});
}
async function helloAsync() {
var x = await testAwait ("hello world");
console.log(x);
}
helloAsync ();
// hello world
在js的运行机制中,程序是单线程运行的,就是说一次只能执行一个任务,其他任务只能等待被执行。任务分为同步任务和异步任务,异步任务又分为宏任务和微任务。可以这样来理解,同步任务放在执行栈(调用堆)中,异步任务放在任务队列中。主线程每次运行时,所有同步任务都按照顺序排列在执行栈(调用堆)中依次等待主线程调用和执行,同步任务都执行完毕之后,再去任务队列中调用微任务和宏任务,执行顺序便是,每清空一次所有的微任务,再执行一次宏任务,以此循环,这个过程又叫js的事件循环机制。 宏任务:所有 js 代码,setTimeOut、setInverter、setImmediate 、 MessageChannel,I/O,UI Rendering等。 微任务:promise 的 then,catch,finaly,process.nextTick,MutationObserver(监测 dom 的变更)等。
console.log("script start");
Promise.resolve().then(function(){
console.log("promise1")
})
setTimeout(function(){
console.log("setTimeout")
},0);
Promise.resolve().then(function(){
console.log("promise2")
})
console.log("script end");
//输出
//script start
//script end
//promise1
//promise2
//setTimeout
微任务 | 宏任务 |
---|---|
promise1 | setTimeout |
promise2 | |
解析: |
console.log('script start');
Promise.resolve().then(function() {
setTimeout(function() {
console.log('setTimeout1');
}, 0);
}).then(function() {
console.log('promise1');
});
setTimeout(function() {
console.log('setTimeout2')
Promise.resolve().then(function(){
console.log('promise2');
})
},0)
console.log('script end');
//输出:
//script start
//script end
//promise1
//setTimeout2
//promise2
//setTimeout1
微任务 | 宏任务 |
---|---|
promise1 | setTimeout2 |
promise2 | setTimeout1 |
console.log('script start')
async function async1() {
await async2()
console.log('async1 end')
}
async function async2() {
console.log('async2 end')
}
async1()
setTimeout(function () {
console.log("setTimeout")
})
new Promise(resolve => {
console.log('promise')
resolve()
}).then(function () {
console.log("promise1")
})
.then(function () {
console.log("promise2")
})
console.log('script end')
分为主线程的执行栈和任务队列 主线程:先执行完同步任务 任务队列:先清空微任务,再执行宏任务 整个程序的输出结果为: script start async2 end promise script end async1 end promise1 promise2 setTimeout 这里可能有同学会疑惑这里的script start和script end为什么不是跟前面案例一样一起输出。其实都是按顺序执行下来的,这个也是,只是前面的案例中途没有输出其他的,反应比较快。
小tip:微任务队列清空后执行宏任务,执行宏任务队列时不会等队列清空再去执行微任务,执行一个宏任务之后就会去检查清空微任务队列,再回来执行宏任务队列。