一文秒懂nodejs中的异步编程(2)

promise可以接then操作,then操作可以接两个function参数,第一个function的参数就是构建Promise的时候resolve的value,第二个function的参数就是构建Promise的reject的error。

promise.then(function(value) { // success }, function(error) { // failure } );

我们看一个具体的例子:

function timeout(ms){ return new Promise(((resolve, reject) => { setTimeout(resolve,ms,'done'); })) } timeout(100).then(value => console.log(value));

Promise中调用了一个setTimeout方法,并会定时触发resolve方法,并传入参数done。

最后程序输出done。

Promise的执行顺序

Promise一经创建就会立马执行。但是Promise.then中的方法,则会等到一个调用周期过后再次调用,我们看下面的例子:

let promise = new Promise(((resolve, reject) => { console.log('Step1'); resolve(); })); promise.then(() => { console.log('Step3'); }); console.log('Step2'); 输出: Step1 Step2 Step3

async和await

Promise当然很好,我们将回调地狱转换成了链式调用。我们用then来将多个Promise连接起来,前一个promise resolve的结果是下一个promise中then的参数。

链式调用有什么缺点呢?

比如我们从一个promise中,resolve了一个值,我们需要根据这个值来进行一些业务逻辑的处理。

假如这个业务逻辑很长,我们就需要在下一个then中写很长的业务逻辑代码。这样让我们的代码看起来非常的冗余。

那么有没有什么办法可以直接返回promise中resolve的结果呢?

答案就是await。

当promise前面加上await的时候,调用的代码就会停止直到 promise 被解决或被拒绝。

注意await一定要放在async函数中,我们来看一个async和await的例子:

const logAsync = () => { return new Promise(resolve => { setTimeout(() => resolve('小马哥'), 5000) }) }

上面我们定义了一个logAsync函数,该函数返回一个Promise,因为该Promise内部使用了setTimeout来resolve,所以我们可以将其看成是异步的。

要是使用await得到resolve的值,我们需要将其放在一个async的函数中:

const doSomething = async () => { const resolveValue = await logAsync(); console.log(resolveValue); }

async的执行顺序

await实际上是去等待promise的resolve结果我们把上面的例子结合起来:

const logAsync = () => { return new Promise(resolve => { setTimeout(() => resolve('小马哥'), 1000) }) } const doSomething = async () => { const resolveValue = await logAsync(); console.log(resolveValue); } console.log('before') doSomething(); console.log('after')

上面的例子输出:

before
after
小马哥

可以看到,aysnc是异步执行的,并且它的顺序是在当前这个周期之后。

async的特点

async会让所有后面接的函数都变成Promise,即使后面的函数没有显示的返回Promise。

const asyncReturn = async () => { return 'async return' } asyncReturn().then(console.log)

因为只有Promise才能在后面接then,我们可以看出async将一个普通的函数封装成了一个Promise:

const asyncReturn = async () => { return Promise.resolve('async return') } asyncReturn().then(console.log)

总结

promise避免了回调地狱,它将callback inside callback改写成了then的链式调用形式。

但是链式调用并不方便阅读和调试。于是出现了async和await。

async和await将链式调用改成了类似程序顺序执行的语法,从而更加方便理解和调试。

我们来看一个对比,先看下使用Promise的情况:

const getUserInfo = () => { return fetch('/users.json') // 获取用户列表 .then(response => response.json()) // 解析 JSON .then(users => users[0]) // 选择第一个用户 .then(user => fetch(`/users/${user.name}`)) // 获取用户数据 .then(userResponse => userResponse.json()) // 解析 JSON } getUserInfo()

将其改写成async和await:

const getUserInfo = async () => { const response = await fetch('/users.json') // 获取用户列表 const users = await response.json() // 解析 JSON const user = users[0] // 选择第一个用户 const userResponse = await fetch(`/users/${user.name}`) // 获取用户数据 const userData = await userResponse.json() // 解析 JSON return userData } getUserInfo()

可以看到业务逻辑变得更加清晰。同时,我们获取到了很多中间值,这样也方便我们进行调试。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wszpjp.html