# async、await与promise
# 1.Promise详解
==Promise是对异步编程的一种解决方案== Promise是一个构造函数,自身有all、reject、resolve这几个方法,原型上有then、catch等方法。Promise的构造函数接收一个函数作为参数,并且在函数中传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数。其中resolve将Promise的状态置为fullfiled,reject将Promise的状态置为rejected。,接下来直接看代码:
console.log('start')
var p = new Promise((resolve, reject) => {
console.log('enter Promise')
//异步操作
setTimeout(() => {
console.log('time out')
console.log(reject)
//执行失败的回调函数,将会在catch中进行接收
reject(123456)
},3000)
})
p.then(r => {
console.log(r)
console.log('promise then')
})
p.catch(e => {
console.log(e)
console.log('promise catch')
console.log(p)
})
console.log(p)
console.log('end')
代码中用setTimeout模拟异步的操作。我们先来观察打印出来的结果:
start
enter Promise
Promise { <pending> }
end
time out
[Function]
123456
promise catch
Promise { <rejected> 123456 }
根据结果分析程序运行的顺序探讨Promise的执行过程:
从上述代码的执行顺序来看,==无论是Promise内部还是处于同一级的其他其他代码,只要是非异步耗时操作都会按顺序在主线程执行==,例如,结果中
1.start 2.enter Promise 3.Promise { <pending> } 4.end
其中2.enter Promise
处在Promise内部但是并不是耗时的异步操作,故直接执行不需要等待;接着程序执行到setTimeout定时任务的异步耗时操作,进入任务队列中等待(后面文章将会进行详解),主线程依次执行完3.Promise { <pending> } 4.end
,此时主线程为空,即没有代码在执行,任务队列得知主线程为空就会开始执行,于是3秒后执行代码5.time out 6.[Function]
,通过reject返回结果回调执行.catch,再依次执行7.123456 8.promise catch 9.Promise { <rejected> 123456 }
。
同时,可以观察到,当Promise中的异步耗时还没有执行,即没有调用resolve和reject时,打印出Promise状态为{ <pending> }
,当调用resolve返回结果时打印Promise状态为{ <rejected> 123456 }
,当然当调用resolve是Promise状态为{ <fulfilled> }
。
# 2.async和await详解
async 用来定义一个返回 AsyncFunction 对象的异步函数,==它会通过一个隐式的 Promise 返回其结果==。如果你在代码中使用了异步函数,就会发现它的语法和结构会更像是标准的同步函数。返回的Promise对象会运行执行(resolve)异步函数的返回结果,或者运行拒绝比如异步函数抛出异常的话,运行执行(reject)异步函数的返回结果。await可以是Promise同步,即不会立即执行Proimse外面(或者说下面)的代码,而await只能用在async标记的函数中,==这样async函数本身就是异步的,而async函数里面的代码是同步的==。async本身是异步的,可以这样理解,async函数执行到await的时候就立即await修饰的代码,并返回结果。async下面的代码,与await等待执行的代码同时执行。(说起来有点拗口),直接看代码和结果分析:
function resolveAfter2Seconds() {
return new Promise(resolve => {
setTimeout(() => {
console.log('time out')
resolve('resolved');
}, 2000);
});
}
/**
* async + await */
async function asyncCall() {
console.log('before');
var result = await resolveAfter2Seconds();
console.log(result);
console.log('after');
}
/**
* 正常函数 */
function call() {
console.log('before');
var result = resolveAfter2Seconds();
console.log(result);
console.log('after');
}
console.log('start')
asyncCall();
//call();
console.log('end')
首先注释掉//call();
,结果为:
start
before
end
time out
resolved
after
然后换成注释掉//asyncCall();
,结果为:
start
before
Promise { <pending> }
after
end
time out
分析:对于async修饰的函数,当用await进行结果修饰时result会等待
resolveAfter2Seconds()
执行完毕并且得到其结果,然后再执行
console.log(result);
console.log('after');
同时观察到打印出来的resulit为resolved
,说明Promse返回不为空;当不用async和await时,观察发现,此时result打印出来为Promise { <pending> }
说明此时的Promise为空,即异步结果还没有返回,最后才执行输出time out
。
# 3.总结与分析
==Promise和async、await都是作为异步编程的一种解决方案==,有时候程序执行异步操作时,如果其后面代码的运行依赖返回的结果,这时候我们就可以运用Promise和async、await进行解决。对于依赖异步结果的代码,在Promise中,将其放在then或者catch中,在async修饰的函数中,将其放在await的后面。 通过上面的的代码演示,async和await解决异步实际上也是封装了Promise,并且以后只要我们看到.then和.catch的形式就能确定其原理一定是Promise,例如axios.