你真的会用async和await么?

这篇具有很好参考价值的文章主要介绍了你真的会用async和await么?。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

背景就是遇到了一个比较烦人的模块,里面的涉及到了大量的async 和 awiat。发现大多人对这个语法糖一知半解,然后大量的滥用,整理一下

async

前置知识:

 Promise.resolve('foo)   ===    new Promise(resolve => resolve('foo'))
 Promise.reject('foo)    ===  new Promise((resolve, reject) => reject('出错了'))

1、async修饰的函数返回一个promise

async function myName() {
  let result = await Promise.resolve("hello")
  let result1 =  await Promise.resolve("hello1")
  console.log(result)
  console.log(result1)
}
myName().then(e => console.log(e))
//hello
//hello1
//undefined (函数没有返回任何的值所以是undefined)

---------------------
async function myName() {
  let result = await Promise.resolve("hello")
  let result1 =  await Promise.resolve("hello1")
  return ({result,result1})
}
myName().then(e => console.log(e))
// { result: 'hello', result1: 'hello1' }

2、async返回的是一个promise,当async中发生错误,这个错误会使返回的promise变为reject状态,从而可以被,catch捕捉到

async function sayHi() {
  throw new Error('抛出一个错误')
}
// 以下四种写法是等价的
sayHi().then(e => console.log(e),e =>console.log(e))
sayHi().then(undefined,e =>console.log(e))
sayHi().then().catch(res => console.log(res))
sayHi().catch(res => console.log(res))

3、注意以下用法,以下用法在项目中使用是极多的

i:以下的这种写法就很好理解了,没问题的

function timeout(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}

asyncPrint('hello world', 50)
// hello world

ii:因为async返回一个promise,所以下述写法完全等同于i的写法

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}
asyncPrint('hello world', 50)
// hello world

你真的会用async和await么?,javascript高级程序设计,javascript,前端,async,await

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
  console.log(8888)
}
async function asyncPrint(value, ms) {
  let res =  timeout(ms)
  console.log(res) 
  console.log(value);
}
asyncPrint('hello world', 50)
// Promise { <pending> }
// hello world
// 8888

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
  console.log(8888)
}

async function asyncPrint(value, ms) {
  let res =  timeout(ms)
  console.log(res) 
  await timeout(ms);
  console.log(value);
}
asyncPrint('hello world', 50)
//Promise { <pending> }
// 8888
// 8888
// hello world
async function timeout(ms,b=2) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
  console.log(8888,b)
}

async function asyncPrint(value, ms) {
  let res =  timeout(ms,9)
  console.log(res) 
  await timeout(ms,6);
  console.log(value);

}
asyncPrint('hello world', 5000)
//Promise { <pending> }
//8888 9
//8888 6
//hello worl

以下对比:async await 修饰的A函数内部执行时序肯定是可控的,但是如果想要在 另一个函数B中也可控(也就是B中调用了A,想让A执行完,在执行B的一些逻辑,那么就需要用awiat来修饰A)

async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
async function asyncPrint(value, ms) {
  await timeout(ms);
  console.log(value);
}
asyncPrint('hello world', 5000);
// 5s后会打印 'hello world'
-------------------------------
async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}
function asyncPrint(value, ms) {
  timeout(ms);
  console.log(value);
}
asyncPrint('hello world', 5000);
// 直接就打印'hello world',并不等5s
-----------------------
async function timeout(ms) {
  await new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
  console.log("打印时机")
}
function asyncPrint(value, ms) {
  timeout(ms);
  console.log(value);
}
asyncPrint('hello world', 5000);
// 立马打印'hello world',5s后打印 '打印时机'

await

await命令只能用在async函数之中,用在普通函数中会报错

await 知识点1

  • await 命令后面是一个promise对象(可以返回这个promise的resolve时的结果并且可以接收,但是reject时就不可以接收到了会报错(可以利用try catch捕捉到reject的结果,或者使用promise的catch可以捕捉到))
  • await后面是简单数据或者负责数据,其实都相当于直接把该值给return出来
async function f() {
  return await 123
}
f().then(e => {console.log(e)})
// 123

async function f() {
  return 123
}
f().then(e => {console.log(e)})
// 123

async function f1() {
   return await {sex: 'man'}
}
f1().then(e => {console.log(e)})
// { sex: 'man' }

async function f2() {
  await {sex: 'man'}
}
f2().then(e => {console.log(e)})
// undefined

await 知识点2

await后面的promise失败了,如何获取到这个失败的值。async里面如果有多个await修饰的promise,返回的resolve的promis并不会阻塞,会继续往下走,但是遇到reject的promise就会直接return出去(有时我们甚至不需要写return)

async function f() {
  return await Promise.resolve('对了');
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 对了

await语句前面没有return,但是reject方法的参数依然传入了catch方法的回调函数。这里如果在await前面加上return,效果是一样的。

async function f() {
  await Promise.resolve('对了');
  await Promise.reject('出错了');
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了
async function f() {
  await Promise.reject('出错了');
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

async function f() {
  return await Promise.reject('出错了');
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出错了

await 知识点三

  • await修饰异步,在async中使用,当promise是resolve时接着往下走
  • 任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行。

1、awiat(直接用),只能接收resolve返回的参数

async function myName() {
  let result = await Promise.resolve("hello")
  let result1 = await Promise.resolve("hello1")
  console.log(result)
  console.log(result1)
}
myName()
// hello
// hello1
async function myName1() {
  let result = await Promise.reject("hello")
  console.log(result)
}
myName1()
// 报错了
------------
async function myName1() {
  let result = await Promise.reject("hello")
  console.log(111111111111111)
  console.log(result)
}
myName1()
// 报错了(console都没走)

2、搭配 try catch 可以用 catch捕捉到reject的错误

async function myName2() {
  try {
    let result = await Promise.reject("hello")
    console.log(result)
  } catch (error) {
    console.log('出错了',error)
  }
}
myName2()
// 出错了 hello

3、try catch ,try内之要有一个promise reject,那么后续的就都不会进行了,直接将第一个reject给catch给出去了

async function myName2() {
  try {
    let result = await Promise.reject("hello")
    console.log(result)
    let result1 = await Promise.resolve("hello word")
    console.log(result1)
  } catch (error) {
    console.log('出错了',error)
  }
}
myName2()
// 出错了 hello
----------------------------------------
// 下方demo为了证明,报错后没有再往后走
async function myName2() {
  try {
    await Promise.reject("hello")
     console.log('走不走')
    let result1 = await Promise.resolve("hello word")
    console.log(result1)
  } catch (error) {
    console.log('出错了',error)
  }
}
myName2()
// 出错了 hello

myName()返回一个promise,这个promise是reject,所以 f函数里的await后面修饰的也就是一个失败的reject了

async function myName() {
   throw new Error('抛出一个错误');
}
async function f() {
  await myName()
}

f()
.then(v => console.log(v))
.catch(e => console.log(e))
// Error: 抛出一个错误

await 知识点四

如何解决一个async函数中有多个await,而当一个await reject时,怎么保证接下来的await继续往下走(当然这种场景一般是不会存在哈,如果前后异步没有依赖的话(学到个名次(这种关系叫做—继发)),为何要控制他们时序呢?正是因为有依赖所以才要控制时序,既然有依赖关系,第一个失败了,按道理后续就是不应该继续执行了)

// 上述演示过这个场景,可以看到只要一个错误,就不往下走了
// 任何一个await语句后面的 Promise 对象变为reject状态,那么整个async函数都会中断执行
async function f() {
  await Promise.reject('出错了')
  console.log('判断是否走不走')
  await Promise.reject('接着出错')
}
f().then().catch(e => console.log(e)) 
// 出错了
  • 思路: 用catch处理一下reject,将错误处理一下,那么catch就不会暴露出去了

解决方案1:

async function k() {
  try {
    await Promise.reject('出错了')
  }catch(e) {
    console.log(e)
  }
  try {
    await Promise.reject('出错了1')
  }catch(e) {
    console.log(e)
  }
  await Promise.reject('接着出错')
}
k().catch(e => console.log(e))
// '出错了'
// '出错了1'
// '接着出错'

解决方案2:

async function l() {
  await Promise.reject('出错了').catch(e => console.log(e))
  await Promise.reject('出错了1').catch(e => console.log(e))
  await Promise.reject('出错了2').catch(e => console.log(e))
  await Promise.reject('接着出错')
}
l().catch(e => console.log(e))
//出错了
//出错了1
//出错了2
//接着出错

await 知识点五

问:await后面的错误如何处理?
答:如果await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject

sync function y() {
  await new Promise((resolve,reject) => {
    throw new Error('出错了')
  })
}
y().catch(e => console.log(e))
// Error: 出错了

错误捕捉(获取)(上面也提到了,分为两种1、try catch 2、用catch捕捉)

async function j() {
  await new Promise((resolve,reject) => {
    throw new Error('出错了')
  }).catch(e => console.log(e))
}
j()
// Error: 出错了
async function j() {
  try {
    await new Promise((resolve,reject) => {
      throw new Error('出错了')
  })
  } catch(e) {
   console.log(e)
  }
}
j()
// Error: 出错了

使用setTimeout模仿异步参考如下

function t() {
  return new Promise((resolve,reject)=> {
   setTimeout(resolve, 5000)
  
  })
}
function y() {
  return new Promise((resolve,reject)=> {
   setTimeout(resolve, 5000)
  })
}
async function f() {
   await t()
   console.log("执行了")
   await y()
   console.log("执行了2")
}
f()
// 5后打印“执行了”,之后又5s打印“执行了2”

new Promise里面的函数是同步执行的,只有当promise有状态的时候才能被await等待到,继续往下走

function t() {
  return new Promise((resolve,reject)=> {
   setTimeout(resolve, 5000)
    console.log(11)
  })
}
function y() {
  return new Promise((resolve,reject)=> {
   setTimeout(resolve, 5000)
   console.log(22)  
  })
}
async function f() {
   await t()
   console.log("执行了")
   await y()
   console.log("执行了2")
}
f()
// 会立即 打印“11”,5s后打印“执行了”,之后立即打印“22”,5s后打印“执行了2”

让继发执行,变为并发执行

1、不作为就行了,不要用async 和await修饰。
2、利用Promise.all()方法,如下:

let [foo, bar] = await Promise.all([getFoo(), getBar()]);

对Promsie.all方法进行解释说明:
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
上面代码中,Promise.all()方法接受一个数组作为参数,p1、p2、p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理

const p = Promise.all([p1, p2, p3]);

以下代码,这时三个db.post()操作将是并发执行,也就是同时执行,而不是继发执行

function dbFuc(db) { //这里不需要 async
  let docs = [{}, {}, {}];

  // 可能得到错误结果
  docs.forEach(async function (doc) {
    await db.post(doc);
  });
}

以下代码,这时三个db.post()操作将是继发执行

async function dbFuc(db) {
  let docs = [{}, {}, {}];

  for (let doc of docs) {
    await db.post(doc);
  }
}

补充

1、new Promise 里面的是同步执行的,resolve是异步,这个resolve执行后,外界才能在这个promise的then方法里拿值
2、promise.then 执行完是个promise,并且可以通过then方法接受then方法里return出去的值
3、new promise没有reslove出去值,使用then方法去获取异步后的结果,是拿不到的。promise resolve出去什么值,就在promise.then里获取到什么值文章来源地址https://www.toymoban.com/news/detail-590034.html

function t() {
  return new Promise((resolve,reject)=> {
   setTimeout(resolve, 5000)
    console.log(11)
    return 4444
  })
}
let r = t().then(function(val) {
  console.log("结果",val)
  return 9999
})

console.log("r",r)

r.then(val => console.log("ll",val))

// 11 --- 立即执行
// r Promise { <pending> } --- 立即执行
// 结果 undefined  --- 5s后
// ll 9999  --- 5s后

到了这里,关于你真的会用async和await么?的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入理解Async/Await:从原理到实践的JavaScript异步编程指南

    理解 async/await 的原理和使用方法是理解现代JavaScript异步编程的关键。这里我会提供一个详细的实例,涵盖原理、流程、使用方法以及一些注意事项。代码注释会尽量详尽,确保你理解每个步骤。 实例:使用async/await进行异步操作 详细解释和注释: 异步函数定义: async func

    2024年02月05日
    浏览(65)
  • 一盏茶的功夫帮你彻底搞懂JavaScript异步编程从回调地狱到async/await

     🎬 江城开朗的豌豆 :个人主页  🔥  个人专栏   :《 VUE 》 《 javaScript 》 ⛺️  生活的理想,就是为了理想的生活 ! 目录 📘 1. 引言 📘 2. 使用方法 📘 3. 实现原理 📘 4. 写到最后   在深入讨论 async/await 之前,我们需要了解一下 JavaScript 的单线程和非阻塞的特性。

    2024年02月08日
    浏览(51)
  • 微信小程序——异步请求使用async/await实现同步

            在小程序的开发中,我们知道网络请求wx.requset是一个异步请求的API,当我们使用它时,会出现请求还没有结束,我们下面写的处理数据的代码就已经执行了从而导致了我们写的程序出现问题,那么我们该怎么解决这个问题呢?今天我们用async/await来实现一下吧。

    2024年02月11日
    浏览(40)
  • uniapp _微信小程序使用async,await(易如反掌的理解清楚)

    async 和 await 是 JavaScript 中处理异步编程的一种方式,它们是 ECMAScript 2017(也被称为 ES8)引入的新特性。 async 用于声明一个函数是异步函数。异步函数在执行时返回一个 Promise 对象。它使得在函数内部可以使用 await 等待异步操作的完成。 await 只能在 as

    2024年03月15日
    浏览(41)
  • 微信小程序中封装请求,使用Async await方法,将异步请求变为同步请求方法

    介绍 微信小程序中,很多 API 都是异步的,无法同步处理。可以使用高级封装,通过 async await 方法来同步处理。 方法 在小程序右上角的 详情 里选择 本地设置 , 勾选 ES6转ES5 ,如下所示: 由于 Async Await 是 ES7 语法,所以在小程序里勾选 es6 转 ES5 会报错: ReferenceError: regene

    2024年02月08日
    浏览(55)
  • async和await

    Node.JS官方文档:https://nodejs.dev/en/ 创建异步函数,并返回相关数值: 一般方式创建 通过async方式创建: 在async声明的函数中可以使用await来调用异步函数 当我们通过await去调用异步函数时候,它会暂停代码的运行 直到异步代码执行有结果时,才会将结果返回 注意 awa

    2024年02月02日
    浏览(40)
  • async/await 编程理解

    博客参考 Asynchronous Programming in Rust ,并结合其中的例子阐述 async 和 await 的用法,如何使用 async 和 await 是本节的重点。 async 和 await 主要用来写异步代码,async 声明的代码块实现了 Future 特性。如果实现 Future 的代码发生阻塞,会让出当前线程的控制权,允许线程去执行别的

    2024年02月12日
    浏览(47)
  • async/await 的用法

    使用场景 在实际开发中,如果你遇到了等第一个请求返回数据完,再执行第二个请求(可能第二个请求要传的参数就是第一个请求接口返回的数据)这个问题。 代码 方法1: 方法2: 先请求接口1,获取到接口1返回结果后,将其作为接口2的参数,再去请求接口2 1、async 用于申明

    2024年02月07日
    浏览(37)
  • Promise、Async/Await 详解

            Promise是抽象异步处理对象以及对其进行各种操作的组件。Promise本身是同步的立即执行函数解决异步回调的问题, 当调用 resolve 或 reject 回调函数进行处理的时候, 是异步操作, 会先执行.then/catch等,当主栈完成后,才会去调用执行resolve/reject中存放的方法。      

    2024年02月14日
    浏览(39)
  • Async In C#5.0(async/await)学习笔记

    此文为Async in C#5.0学习笔记 方式一:基于事件的异步Event-based Asynchronous Pattern (EAP). 方式二:基于IAsyncResult接口的异步 方式三:回调 方式四:使用Task,尤其是TaskT 共同的缺陷:必须将方法分为两部分 乱如麻的递归 async/await 注意,下面这样操作可能会有隐患,当firstTask有异常时

    2024年01月22日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包