首页 > 其他分享 >JS 异步

JS 异步

时间:2023-02-19 22:55:19浏览次数:49  
标签:异步 console log await JS Promise async

回调函数

ES5:使用回调函数处理异步执行的结果

setTimeout(() => {
  console.log('1')
  setTimeout(() => {
    console.log('2')
    setTimeout(() => {
      console.log('3')
      //....
    }, 1000)
  }, 1000)
}, 1000)

多重回调嵌套导致可读性变差,称为回调地狱(Callback Hell)

良好的编程习惯:http://callbackhell.com/

Promise

ES6语法

承诺,承诺在未来的某个时刻返回数据。

优点:使用链式结构将多个异步操作串联起来,解决了回调地狱问题

new Promise(...)
.then(...)
.then(...)
.then(...)
.catch(...)
.finally(...)

Promise.then() 和 Promise.catch() 都返回 Promise 对象,示例:

new Promise(function (resolve, reject) {
  setTimeout(() => {
    var start = 3
    resolve(start)
  }, 1000)
})
  // 异常之后、catch之前的部分不被执行。类似 try-catch中的异常捕获
  .then(function (res) {
    console.log('1st then, ', res)
    throw Error('e')
    res *= 2
    return res
  })
  .then(function (res) {
    console.log('2nd then, ', res)
    return res * 2
  })
  .then((res) => {
    console.log('3rd then, ', res)
  })
	// 异常捕获
  .catch((err) => {
    console.log('err, ', err)
  })
  // 异常之后的then可执行
  .then(() => {
    console.log('after catch')
  })
  // 清理、结尾工作,比如关闭进度条
  .finally(() => {
    console.log('final')
  })

基于Promise的异步请求

<script>
  'use strict'
  function reqPromise(URL) {
    return new Promise((resolve, reject) => {
      var xhr = new XMLHttpRequest()
      xhr.open('GET', URL)
      xhr.onload = function () {
        if (xhr.status == 200) {
          resolve(xhr.response)
        } else {
          reject(Error('error code: ', xhr.statusText))
        }
      }
      xhr.onerror = function () {
        reject(Error('network error.'))
      }
      xhr.send()
    })
  }
  reqPromise('https://jsonplaceholder.typicode.com/posts/1').then(
    (resp) => {
      console.log('yay!, ', JSON.parse(resp))
    },
    (Error) => {
      console.log(Error)
    }
  )
</script>

基于fetch-api(XMLHttpRequest的升级版) 的异步请求

fetch('https://jsonplaceholder.typicode.com/posts/1', {
  method: 'get',
})	// fetch 返回 Promise对象
  .then((resp) => {
    return resp.json()	// Body.json() 返回 Promise 对象
  })
  .then((data) => {
    console.log(data)
  })

参考:MDN · Promise

async/await

基于 Promise 之上的语法糖,使异步操作简单、明了。

注意:

  • 使用 async 将函数标记为异步函数(返回 Promise 对象的函数)

  • 在异步函数中调用其他的异步函数,不再使用 then,而是使用await,await 会等待 Promise 执行完成返回最终的结果(await 底层基于 Promise 和事件循环机制实现,在等待时会处理其他任务,比如页面更新等等)

async function fun() {
  const resp = await fetch('https://jsonplaceholder.typicode.com/posts/1')
  const data = await resp.json()
  console.log(data)
}

fun();

await 陷阱 ✧

1、并行操作

async function f() {
  const promiseA = await fetch('http://...')
  const promiseB = await fetch('http://...')	//两个 fetch 不是并行的
  
  //...
}

// 更高效的做法:将Promse用Promise.all组合起来,然后再去await,修改后的程序运行效率会直接提升一倍
async function f() {
  const promiseA = fetch('http://...')
  const promiseB = fetch('http://...')
  
  const [a, b] = await Promise.all([promiseA, promiseB])
}


不使用Promise.all时:

使用Promise.all后:

2、再循环中执行异步操作,不能调用 forEach或map 这样的方法

async function f1() {
  [1, 3, 5].forEach(async (i) => {	//⚠️:虽然使用了await,但forEach会立刻返回,并不会暂停等到所有异步操作都执行完毕!
    await doSomethingOperation();
  })
  consolo.log('done')
}
f1();


//解决方法一:使用传统的for循环 =》 会暂停等到所有异步操作都执行完毕
async function f2() {
  for (let i of [1, 2, 3]) {
    await doSomething();
  }
  consolo.log('done')
}

//解决方法二:使循环中的操作并发执行,使用 for await:
async function f3() {
  const promises = [
    someAsyncOp();
    someAsyncOp();
    someAsyncOp();  
  ]
  for await (let result of promises) {
    // ....
  }
  console.log('done')
}

3、不能在全局中或普通函数中使用 await,而只能被用在异步函数中

async funcion f() {
  await doSomething();
}
f();

// 更简洁
(async ()=> {
  doSomething()
})();

有了 async/await,几乎用不到 Promise 及他的 then、catch 方法

其他:引入并使用 async 模块

Reference

https://www.bilibili.com/video/BV1WP4y187Tu

标签:异步,console,log,await,JS,Promise,async
From: https://www.cnblogs.com/engure/p/17135865.html

相关文章

  • Python 异步: 同时运行多个协程(10)
    asyncio的一个好处是我们可以同时运行许多协程。这些协同程序可以在一个组中创建并存储,然后同时一起执行。这可以使用asyncio.gather()函数来实现。让我们仔细看看。1......
  • js得到当前窗口内的宽度和高度
    vars="";s+="\r\n网页可见区域宽:"+document.body.clientWidth;s+="\r\n网页可见区域高:"+document.body.clientHeight;s+="\r\n网页可见区域宽:"+document.......
  • JS字符串和json转换
    <head><scriptsrc="jquery-1.8.0.min.js"type="text/javascript"></script><scriptsrc="jquery.json-2.4.js"type="text/javascript"></script></head>varst......
  • JS 差集
    <htmlxmlns="http://www.w3.org/1999/xhtml"xml:lang="zh"lang="zh"dir="ltr"><scripttype="text/javascript">vararr1=[1,3,4,5,6,7,8];var......
  • JS取queryString
    String.prototype.GetValue=function(para){varreg=newRegExp("(^|&)"+para+"=([^&]*)(&|$)");varr=this.substr(this.indexOf("\?")+1).match(re......
  • jsp开发基础
    1、什么时动态网页?指的是能够通过不同的操作返回不同的功能及数据,具有交互功能。常见的开发模式:B/S架构:游览器和服务器C/S架构:客户端和服务器B/S架构的执行原理:基于......
  • 前端require.js的基本用法
    require.js是一个js脚本加载器(模块化加载),它遵循AMD(AsynchronousModuleDefinition)规范,实现js脚本的异步加载,不阻塞页面的渲染和其后的脚本的执行,并提供了在加载完成之后......
  • 基于jsplumb构建的流程设计器
    项目背景最近在准备开发工作流引擎相关模块,完成表结构设计后开始着手流程设计器的技术选型,调研了众多开源项目后决定基于jsplumb.js开源库进行自研开发,保证定制化的便捷性,......
  • 基于jsplumb构建的流程设计器
    项目背景最近在准备开发工作流引擎相关模块,完成表结构设计后开始着手流程设计器的技术选型,调研了众多开源项目后决定基于jsplumb.js开源库进行自研开发,保证定制化的便捷性......
  • js performance checker All In One
    jsperformancecheckerAllInOnejs性能检测console.timeconsole.timeLogconsole.timeEndconsole.time(`⏰performance`);for(leti=0;i<10**3;......