js中的promise与async函数一些细节

学习的时候遇到一个问题

async function getData() {
  return await Promise.resolve('I made it!');
}

const data = getData();
console.log(data);

学习的时候看到说await会使得async函数中断,像执行同步代码那样子,直到返回值回来再执行下面的代码,于是乎就觉得await返回的值是一个值,所以上述例子第一眼看上去觉得答案是I made it! 但是答案是Promise {<pending>},带着不解,我在控制台上随便试了一波

首先确定一下返回值的问题

async function getData() {
  return 'I made it!';
}

const data = getData();
console.log(data);

结果是Promise {<fulfilled>: 'I made it!'},这就确定了一点,async函数的返回值会封装成一个promise对象,至于这个promise对象的状态是pending还是fullfilled就取决于具体的返回值了。
再对上面的例子进行修改,确定一下函数内部的await的返回值

async function getData() {
  let a =  await Promise.resolve('I made it!');
  console.log(a)
  return a
}

const data = getData();
console.log(data);

结果是
在这里插入图片描述
和印象里的没错,await是会返回promise对象的值,但是这个顺序又让我有疑问了,按理说应该是先执行getData()函数,再执行log,那不是应该先是打印I made it! 再打印Promise {<pending>}吗?带着这个疑问,我再修改一下例子

async function getData() {
  console.log(111)
  let a =  await Promise.resolve('I made it!');
  console.log(222)
  console.log(a)
  return a
}

const data = getData();
console.log(data);

结果是:
在这里插入图片描述
根据输出来推测一波,首先执行getData()函数,getData()函数是一个async函数,返回值是await声明的promise对象;再执行getData()的时候,111在await之前,最先被执行,所以最先被打印;接着到await语句,前面说过,这时候函数内部中断,直到promise返回,所以下面的222a的值的打印都被延迟了,总的来说就是,那些都被放进异步的进程里面了,所以此时函数内部的同步进程以已经执行到了return并把当时还未返回值的promise(pengding状态)送给了data,这时候getData()的同步进程已经执行完(看到后面再回头看这里就发现漏洞了,其实这时候getData函数被堵塞住了,而async函数无论有无return都是会返回一个promise对象,所以此时getdata函数并未执行完,但是确实是将内部操作放到异步去执行,然后紧接着执行主动进程的任务),外界的代码接下来打印data,由于异步进程肯定不够主动进程解析代码快,所以此时data的状态还是pendding,就打印了Promise {<pending>},后续就是getdata内部的异步进程开始执行,打印222,打印a的值;
我们进一步验证一下上面的推测,如果再执行完getdata之后先延迟1s再打印data,结果应该是

111
222
I made it !
promise{<fullfilled>}
async function getData() {
  console.log(111)
  let a =  await Promise.resolve('I made it!');
  console.log(222)
  console.log(a)
  return a
}

const data = getData();
setTimeout(()=>console.log(data),1000)

结果是符合预期的
当然,上述的同步异步进程是我的一种猜测,还是得找官方文档,

1.await 表达式会暂停整个 async 函数的执行进程并出让其控制权,只有当其等待的基于 promise 的异步操作被兑现或被拒绝之后才会恢复进程。
2.async 函数的函数体可以被看作是由 0 个或者多个 await 表达式分割开来的。从第一行代码直到(并包括)第一个 await 表达式(如果有的话)都是同步运行的。这样的话,一个不含 await 表达式的 async 函数是会同步运行的。然而,如果函数体内有一个 await 表达式,async 函数就一定会异步执行。
3.在 await 表达式之后的代码可以被认为是存在在链式调用的 then 回调中,多个 await 表达式都将加入链式调用的 then 回调中,返回值将作为最后一个 then 回调的返回值。

这么看来,还需要验证一个例子,这个是为了验证return是在await拿到返回值之前还是之后

async function getData() {
  console.log(111)
  let a =  await Promise.resolve('I made it!');
  console.log(222)
  console.log(a)
  return 123
}

const data = getData();
console.log(data);

在这里插入图片描述
根据答案可以知道,return是在await之后,和官方文档一样,执行到await会中止同步进程,进入异步进程直到异步进程结束再最后返回,但是我们也知道了一点,如果在async函数内部的异步进程没有结束,没有把主动权交还给主动进程,此时的async函数的返回值(无论有无return)都是pending状态的promise对象,但是有一点就是同步异步进程不会影响,否则如果getData函数卡在了await的异步进程,那为什么外面打印data会顺利进行呢?答案就是前面分析的异步进程和主动进程不会影响,当await执行异步操作的时候,外面的同步操作也在进行

总结:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: PromiseJavaScript一种用于异步编程的工具。它可以解决回调地狱问题,让异步代码看起来更像同步代码。Promise对象有三种状态:pending(进行)、fulfilled(已成功)和rejected(已失败)。 async 和 await 是 JavaScript 的关键字,它们主要用于处理异步代码。async 用于声明一个函数是异步的,await 用于等待一个异步操作的结果。使用 async 和 await 可以让异步代码看起来更像同步代码,并且可以使用 try-catch 来处理错误。 ### 回答2: JavaScript有三种异步操作方式:callback、Promiseasync/await。 1. Callback 回调函数 回调函数是最早的异步操作方法,他通常采用匿名函数的形式,在函数执行完成后将结果作为参数传入回调函数,然后再继续执行后续操作。缺点明显,若回调函数嵌套层次过多,将造成代码阅读困难,也不容易维护。 2. Promise Promise在ES6被引入,他提供了在异步操作完成后返回结果的能力,而且代码结构清晰,可读性好。Promise 有三种状态: * Pending(未完成) * Fulfilled(已完成) * Rejected(已失败) 如果目标任务完成,则为Fulfilled,如果任务出现错误,则为Rejected。Promise有两个关键字来控制异步操作:resolve和reject。当异步操作执行成功,就会调用resolve方法并传入需要返回的内容;当异步操作失败,就会调用reject方法并返回错误信息。一般结合then方法来使用。 3. async/await async/await 是ES7新添加的异步方式,在ES8被正式列入标准语言async/await 基于Promise,它是一种更加优雅的语法结构,可以让异步代码看起来和同步代码风格类似。async/await 是一个相对简洁明了的解决方案,使异步操作符合同步操作的语法风格。 在 async 函数内部,可以使用await命令,就像在同步操作等待返回结果一样。 在使用 async/await 时,必须使用try-catch包裹代码块,以捕获异常和错误信息。 async/await 并不是一种新型异步解决方案,而是一种更加方便,更加优雅的异步编程方式,使得开发人员能够更好地控制异步操作和错误处理。 总之,随着 JavaScript 的不断发展,异步编程已经成为一种必备的编程技巧。在实际编程,理解 Promiseasync/await 和 callback 的具体用法,以及它们的优缺点是非常重要的。根据不同的场景和需求,选择最适合的异步操作方式,能够让你的代码更为优雅、简洁和可读。 ### 回答3: JavaScript 是一门异步编程语言,而 Promiseasync/await 是 JavaScript 语言的两种异步编程技术,用于解决异步编程的问题。 Promise 是一种解决 JavaScript 异步编程的技术,它是 ES6 新增的一个对象。Promise 代表着一个异步操作的最终结果,可以是成功或失败。使用 Promise 的好处是,可以更加优雅地处理异步编程,避免了传统回调函数的回调地狱问题,使代码更容易维护和扩展。 Promise 构造函数可以接受一个函数作为参数,该函数带有 resolve 和 reject 函数作为参数。当 Promise 进入 resolved 状态时,调用 resolve 函数并返回结果;当 Promise 进入 rejected 状态时,调用 reject 函数并返回一个 error 对象,表示异步操作发生了错误。通常,使用 then 方法来处理 Promise 的结果,catch 方法来处理 Promise 的错误结果。 async/await 是 ES8 新增的异步编程技术,它也是使用 Promise 的基础之上开发的技术。async/await 的优势在于,可以以同步代码的方式编写异步代码,使代码更加易读易写。 在使用 async/await 时,async 关键字用来修饰函数,表示该函数是一个异步函数,await 关键字用来等待 Promise 返回的结果。当在异步函数使用 await 关键字时,代码会暂停执行,等待 Promise 返回结果,然后继续执行异步函数的其他代码。如果 Promise 返回结果成功,使用 return 关键字返回结果;如果 Promise 失败,则使用 throw 关键字抛出异常。 总的来说,Promiseasync/await 都是解决 JavaScript 异步编程的好技术,Promise 更加实用,可以避免回调地狱问题,而 async/await 则可以让异步代码更加易读易写。在开发,可以根据实际需求选择适合的技术来处理异步操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SuperHaker~

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值