Web语言】promise和async await的区别是什么?什么情况下适合用?

2021-01-28 09:07发布

9条回答
无需指教
2楼 · 2021-01-28 09:34

Promise基础用法

new Promise( function(resolve, reject) {...} /* executor */  )1

promise是异步请求时会使用,一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)。在调用时候会传入resolve和reject参数,resolve是状态由pending至fulfilled,即状态成功回调。reject是失败回调。
在这里插入图片描述
Promise 是用来管理异步编程的,它本身不是异步的,new Promise的时候会立即把executor函数执行
代码片段1:

let p1 = new Promise(()=>{
    setTimeout(()=>{
      console.log(1)
    },0)
    console.log(2)
  })console.log(3) // 2 3 11234567

上面代码会先执行promise中的回调,打印2,然后继续执行打印3,由于打印1延时处理,属于开启的新任务,会等其他任务执行完成,再执行1。

代码片段2:

let p1 = new Promise((resolve,reject)=>{
  console.log(1);
  resolve('执行promise')
  console.log(2)})// then:设置成功或者失败后处理的方法p1.then(result=>{
 //p1延迟绑定回调函数
  console.log('成功 '+result)},reason=>{
  console.log('失败 '+reason)})console.log(3)// 1// 2// 3// 成功 执行promise1234567891011121314151617

Promise 采用了回调函数延迟绑定技术,在执行 resolve 函数的时候,回调函数还没有绑定,那么只能推迟回调函数的执行
代码片段2中,先执行打印1,p1中resolve的回调函数还没绑定,会出发微任务,将p1.then暂存起来,继续执行打印2,打印3,同步任务执行完毕后,去执行微任务,执行.then中方法。

代码片段3:

new Promise(resolve=>{
    resolve(a) // 报错 // 这个executor函数执行发生异常错误,决定下个then失败方法会被执行}).then(result=>{
    console.log(`成功:${result}`)
    return result*10},reason=>{
    console.log(`失败:${reason}`)// 执行这句时候,没有发生异常或者返回一个失败的Promise实例,所以下个then成功方法会被执行// 这里没有return,最后会返回 undefined}).then(result=>{
    console.log(`成功:${result}`)},reason=>{
    console.log(`失败:${reason}`)})// 失败:ReferenceError: a is not defined// 成功:undefined1234567891011121314151617
  • 不论是成功的方法执行,还是失败的方法执行(then中的两个方法),凡是执行抛出了异常,则都会把实例的状态改为失败。

  • 方法中如果返回一个新的Promise实例(比如上例中的Promise.reject(1)),返回这个实例的结果是成功还是失败,也决定了当前实例是成功还是失败。

  • 剩下的情况基本上都是让实例变为成功的状态,上一个then中方法返回的结果会传递到下一个then的方法中

async & await

ES7中新增的异步编程方法,async/await的实现是基于 Promise的,简单而言就是async 函数就是返回Promise对象
1、带async关键字的函数,是声明异步函数,返回值是promise对象,如果async关键字函数返回的不是promise,会自动用Promise.resolve()包装。

async function test() {
    return 'test'}test(); //Promise {: "test"}1234

2、await等待右侧表达式的结果,这个结果是promise对象或者其他值。
遇到await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码。以下面的代码分析:

 async function test1() {
            console.log('start test1');
            console.log(await test2());
            console.log('end test1');
        }
        async function test2() {
            console.log('test2');
            return 'return test2 value'
        }
        test1();
        console.log('start async');
        setTimeout(() => {
            console.log('setTimeout');
        }, 0);
        new Promise((resolve, reject) => {
            console.log('promise1');
            resolve();
        }).then(() => {
            console.log('promise2');
        });
        console.log('end async');123456789101112131415161718192021

执行的结果
在这里插入图片描述

· 首先执行宏任务,执行test1函数,执行console.log(‘statr test1’)

· 遇到await,先执行右边test2中的console.log(‘test2’),test2())执行完成后返回Promise {: “return test2 value”},是promise对象,推到微任务队列中**,执行test1外面的同步代码

· 执行console.log(‘start async’);

· 遇到setTimeout,推到到下个宏任务队列中

· 执行Promise里面的同步代码console.log(‘promise1’)

· 运行到promise().then,发现是promise对象,推到微任务队列中

· 执行console.log(‘end async’)

· **test1外面的同步代码执行结束后,回到test1中,console.log(await

· 此时第一个宏任务结束,执行所有的微任务,因为微任务队列先进先出,所以先执行console.log(‘return test2 value’) ,执行test2完成后,后面的代码不再阻塞,执行console.log(‘end test1’);后执行console.log(‘promise2’)
· 执行下个宏任务,即执行console.log(‘setTimeout’);

补充下有关宏任务和微任务的知识

宏任务和微任务都是队列,宏任务有script、setTimeout、setInterval等,微任务有Promise.then catch finally、process.nextTick等,宏任务和微任务的关系如下:
在这里插入图片描述

先执行第一个宏任务,执行结束后,执行所有的微任务,然后执行下个宏任务。


小磊子
3楼 · 2021-01-28 09:39

什么是Async/Await?

 

  async/await是写异步代码的新方式,以前的方法有回调函数和Promise。
  async/await是基于Promise实现的,它不能用于普通的回调函数。
  async/await与Promise一样,是非阻塞的。
  async/await使得异步代码看起来像同步代码,这正是它的魔力所在。

 Async/Await语法

 假设函数getJSON返回值是 Promise,并且 Promise resolves 有一些JSON 对象。我们只想调用它并且记录该JSON并且返回完成。

  1)使用Promise:

 

复制代码

    const makeRequest = () =>
        getJSON().then(data => {
            console.log(data)            return "done"
        })

    makeRequest()

复制代码

 

  2)使用Async:

 

 

复制代码

    const makeRequest = async () => {        // await getJSON()表示console.log会等到getJSON的promise成功reosolve之后再执行。
        console.log(await getJSON)        return "done"
    }

    makeRequest()

复制代码

 

 区别:

  1)函数前面多了一个aync关键字。await关键字只能用在aync定义的函数内。async函数会隐式地返回一个promise,该promise的reosolve值就是函数return的值。(示例中reosolve值就是字符串”done”)
  2)第1点暗示我们不能在最外层代码中使用await,因为不在async函数内。例如:

复制代码

    // 不能在最外层代码中使用await
    await makeRequest()    // 这是会出事情的 
    makeRequest().then((result) => {        // 代码
    })

复制代码


lemon
4楼 · 2021-01-28 09:50

promise是一个异步编程的解决方案,减少了代码量,提高了代码可读性,有效解决了回调地狱问题.它可以链式调用。

async的用法,它作为一个关键字放到函数前面,调用该函数会返回一个 promise对象如果只是async, promise差不多,但有了 await就不一样了

await关键字只能放到 async函数里面, await是等待的意思。其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise对象的表达式,它等待的是 promise对象的执行完毕,并返回结果。


三岁奶猫
5楼 · 2021-01-28 11:07

promise是一个异步编程的解决方案,减少了代码量,提高了代码可读性,有效解决了回调地狱问题.它可以链式调用。

async的用法,它作为一个关键字放到函数前面,调用该函数会返回一个 promise对象如果只是async, promise差不多,但有了 await就不一样了

await关键字只能放到 async函数里面, await是等待的意思。其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise对象的表达式,它等待的是 promise对象的执行完毕,并返回结果。


一朵大红花啊
6楼 · 2021-01-28 11:26

Promise 采用了回调函数延迟绑定技术,在执行 resolve 函数的时候,回调函数还没有绑定,那么只能推迟回调函数的执行
代码片段2中,先执行打印1,p1中resolve的回调函数还没绑定,会出发微任务,将p1.then暂存起来,继续执行打印2,打印3,同步任务执行完毕后,去执行微任务,执行.then中方法。

清屿
7楼 · 2021-01-28 14:06

promise是一个异步编程的解决方案,减少了代码量,提高了代码可读性,有效解决了回调地狱问题.它可以链式调用。

async的用法,它作为一个关键字放到函数前面,调用该函数会返回一个 promise对象如果只是async, promise差不多,但有了 await就不一样了

await关键字只能放到 async函数里面, await是等待的意思。其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise对象的表达式,它等待的是 promise对象的执行完毕,并返回结果。


py大白
8楼 · 2021-01-29 09:27

promise是一个异步编程的解决方案,减少了代码量,提高了代码可读性,有效解决了回调地狱问题.它可以链式调用。

async的用法,它作为一个关键字放到函数前面,调用该函数会返回一个 promise对象如果只是async, promise差不多,但有了 await就不一样了

await关键字只能放到 async函数里面, await是等待的意思。其实它后面可以放任何表达式,不过我们更多的是放一个返回 promise对象的表达式,它等待的是 promise对象的执行完毕,并返回结果。


征戰撩四汸
9楼 · 2021-10-21 14:31

抽象表达:Promise 是JS中进行异步编程的新的解决方案(旧的是谁?=> 纯回调的形式)

具体表达:

  • 从语法上来说:Promise 是一个构造函数

  • 从功能上来说:Promise 对象用来封装一个异步操作并可以获取其结果

async 函数的返回值为 Promise 对象,async 函数返回的 Promise 的结果由函数执行的结果决定


await 右侧的表达式一般为 promise 对象, 但也可以是其它的值

  1. 如果表达式是 promise 对象, await 返回的是 promise 成功的值

  2. 如果表达式是其它值, 直接将此值作为 await 的返回值


await 必须写在 async 函数中, 但 async 函数中可以没有 await,如果 await 的 Promise 失败了, 就会抛出异常, 需要通过 try...catch 捕获处理。

Async/await 实际上只是一种基于 promises 的糖衣语法糖,Async/await 和 promises 一样,都是非堵塞式的,Async/await 让异步代码更具同步代码风格,这也是其优势所在。

async function 用来定义一个返回 AsyncFunction 对象的异步函数。异步函数是指通过事件循环异步执行的函数,它会通过一个隐式的 Promise 返回其结果,。如果你在代码中使用了异步函数,就会发现它的语法和结构会更像是标准的同步函数。

await 操作符用于等待一个 Promise 对象。它只能在异步函数 async function 中使用。


Async/await 比 Promise 更优越的表现

简洁干净,使用 async/await 能省去写多少行代码

错误处理,async/wait 能用相同的结构和好用的经典 try/catch 处理同步和异步错误,错误堆栈能指出包含错误的函数。

调试,async/await 的一个极大优势是它更容易调试,使用 async/await 则无需过多箭头函数,并且能像正常的同步调用一样直接跨过 await 调用。


相关问题推荐

  • 回答 24

    1、Web前端人才需求量大据国内第三方数据统计,未来五年我国信息化人才总需求高达1500万-2000万人。其中网络工程UI设计Web前端等人才的缺口最为突出,所以2020年Web前端的市场需求很大。更有甚者目前不仅大型互联网公司相继成立了专属的Web前端部门,中小型公...

  • 回答 6

    可以在后台返回数据之后调用table的toggleRowSelection方法来实现默认勾选

  • 回答 13

    一个HTML文件,如果超过了500行,则HTML代码会自动保护,自动保护就不会全部显示HTML代码的颜色HTML代码不高亮,点击右下角切换语言为XML,即HTML代码部分高亮,带颜色再切换为HTML,则CSS和javascript部分高亮,带颜色显示代码...

  • 回答 16
    已采纳

    1、行业发展好从我们身边的方方面面考虑,互联网行业无疑是现在发展前景最好的行业之一。WEB前端作为互联网+时代,用户体验为王的掌控者,同时单页面应用、数据可视化等这些都是通过前端开发者提高用户体验的方式。所以待遇是水涨船高的。2、人才需求大互联网...

  • 回答 2

    这两个事件都是在js原生开发时经常会用到的,比如需要对页面dom进行动态处理,这时就需要用到DOMContentLoaded和[removed]事件,大家都知道,就是在dom构建完毕后,才可以对dom元素进行操作,否则会获取不到相应的dom元素,但是DOMContentLoaded和[removed]还...

  • 回答 11

    基本概念CookieCookie 是小甜饼的意思。顾名思义,cookie 确实非常小,它的大小限制为4KB左右。它的主要用途有保存登录信息,比如你登录某个网站市场可以看到记住密码,这通常就是通过在 Cookie 中存入一段辨别用户身份的数据来实现的。localStoragelocalStor...

  • 回答 4

    下面我们要在这个对象上挂载一个extend方法,用于让开发者为我这个对象添加功能和方法。12345var $ = {   extend:function(ob){      /**暂时不管里面写什么**/   }  }现在,我们就在$这个对象上添加了一个extend方法,外部可以通过$.extend(obj...

  • 回答 2

    在vscode 头疼的问题是 用浏览器查看网页!会是以文件夹的方式打开的!  我遇到这个问题 我还重新配置了Apache    ! 但是现在可以解决:使用vscode  ==================== 打开cmd   : 在cmd 控制台中输入  :   1.运行cnpm install live-server...

  • 回答 1

    对于这三种渲染方式个人觉得对于字符串拼接、模板字符串更适合于在初级阶段使用,其中模板字符串相对字符串拼接更易于上手,artTemplate适合于在有一定基础之后再学习使用。

没有解决我的问题,去提问