前端异步解决方案大全(2021版)(四)

简介: 前端异步解决方案大全(2021版)

3、async await (重点)

es7新增的 async函数。

可以更舒适地与promise协同工作,它叫做async/await,它是非常的容易理解和使用。

格式以及知识点

async function aa(){
        await '任务1'
        await '任务2'
}

async:

让我们先从async关键字说起,它被放置在一个函数前面。就像下面这样:

async function timeout() {
  return 'hello world';
}

函数前面的async一词意味着一个简单的事情:这个函数总是返回一个promise,如果代码中有return <非promise>语句,JavaScript会自动把返回的这个value值包装成promise的resolved值。


例如,上面的代码返回resolved值为1的promise,我们可以测试一下

async function f() {
    return 1
}
f().then(alert) // 弹出1

我们也可以显式的返回一个promise,这个将会是同样的结果:

1. async function f() {
2. return Promise.resolve(1)
3. }
4. f().then(alert) // 弹出1

所以,async确保了函数返回一个promise,即使其中包含非promise,这样都不需要你来书写繁杂的Promise,够简单了吧?但是不仅仅只是如此,还有另一个关键词await,只能在async函数里使用,同样,它也很cool。

await:

// 只能在async函数内部使用
let value = await promise

关键词await可以让JavaScript进行等待,直到一个promise执行并返回它的结果,JavaScript才会继续往下执行。

以下是一个promise在1s之后resolve的例子:

async function f() {
    let promise = new Promise((resolve, reject) => {
        setTimeout(() => resolve('done!'), 1000)
    })
    let result = await promise // 直到promise返回一个resolve值(*)
    alert(result) // 'done!' 
}
f()


函数执行到(await)行会‘暂停’,不再往下执行,当promise处理完成后重新恢复运行, resolve的值成了最终的result,所以上面的代码会在1s后输出'done!'


我们强调一下:await字面上使得JavaScript等待,直到promise处理完成,


然后将结果继续下去。这并不会花费任何的cpu资源,因为引擎能够同时做其他工作:执行其他脚本,处理事件等等。


这只是一个更优雅的得到promise值的语句,它比promise更加容易阅读和书写。


注意不:能在常规函数里使用await


如果我们试图在非async函数里使用await,就会出现一个语法错误:

function f() {
   let promise = Promise.resolve(1)
   let result = await promise // syntax error
}
//Uncaught SyntaxError: await is only valid in async function

如果我们忘记了在函数之前放置async,我们就会得到这样一个错误。如上所述,await只能在async函数中工作。

就以前面几个案例可能还看不出async/await 的作用,如果我们要计算3个数的值,然后把得到的值进行输出呢?

async function testResult() {
    let first = await doubleAfter2seconds(30);
    let second = await doubleAfter2seconds(50);
    let third = await doubleAfter2seconds(30);
    console.log(first + second + third);
}

6秒后,控制台输出220, 我们可以看到,写异步代码就像写同步代码一样了,再也没有回调地域了。


再来一个看看:先来个问题


readFile('./01-Promise.js') 运行结果是Promise, 但是我们使用 async await之后, 它的结果是具体的数据了?


用到了Node.js里的fs模块,fs模块是文件模块,可以操作文件,readFile()是读一个文件,不了解的可以看Node.js官方文档

const fs = require('fs')//导入fs模块
const readFile = (filename) =>{
  return new Promise((resolve,reject)=>{
    fs.readFile(filename,(err,data)=>{
      resolve(data.toString())
    })
  })
}
const asyncFn = async() => {
   //const f0 = eadFile('./01-Promise.js') //类似{value: '文件内容', done: false}
  const f1 = await readFile('./01-Promise.js') //文件内容
  //const f1 =  readFile('./01-Promise.js').then(data=>data)
  const f2 = await readFile('./02-generator.js') //文件内容
  console.log( f1 )
  console.log( f2 )
}
asyncFn()

readFile()定义了一个Promise方法读取文件,这里有个坑,我们现在是在里面返回出数据了的,要知道这里面有3层函数,如果不用new Promise这个方法,大家可以试试用常规方法能不能返回数据,先透个底拿不到,大家可以试试。


asyncFn()输出了文件内容,在const f1 = eadFile('./01-Promise.js')这一句这一句会打印出出一个Promise{'文件内容'},有点类似前面的generator函数输出的{value: '', done: false},只不过省略了done,大家知道,我们读文件,肯定是要里面的内容的,如果输出 Promise{'文件内容'} ,我们是不好取出内容的,但是await很好的帮我们解决了这个问题,前面加上await直接输出了文件内容。


所以:这个问题可以有个小总结


async函数使用了generator函数的语法糖 , 它直接生成对象 {value: '',done:false} await 直接将value提取出来了

通过Promise + async,我们可以把多层函数嵌套(异步执行)的里层函数得到的数据 返回出来


关于async/await总结


放在一个函数前的async有两个作用:


使函数总是返回一个promise,允许在这其中使用await

promise前面的await关键字能够使JavaScript等待,直到promise处理结束。然后:


如果它是一个错误,异常就产生了,就像在那个地方调用了throw error一样。

否则,它会返回一个结果,我们可以将它分配给一个值

他们一起提供了一个很好的框架来编写易于读写的异步代码。


有了async/await,我们很少需要写promise.then/catch,但是我们仍然不应该忘记它们是基于promise的,因为有些时候(例如在最外面的范围内)我们不得不使用这些方法。Promise.all也是一个非常棒的东西,它能够同时等待很多任务。


4、node.js nextTick setImmidate

nextTick vs setImmediate

(1).什么是轮询

nodejs中是事件驱动的,有一个循环线程一直从事件队列中取任务执行或者I/O的操作转给后台线程池来操作,把这个循环线程的每次执行的过程算是一次轮询。

(2).setImmediate()的使用

即时计时器立即执行工作,它是在事件轮询之后执行,为了防止轮询阻塞,每次只会调用一个。

详情:Window.setImmediate() - Web APIs | MDN

(3).Process.nextTick()的使用

它和setImmediate()执行的顺序不一样,它是在事件轮询之前执行,为了防止I/O饥饿,所以有一个默认process.maxTickDepth=1000来限制事件队列的每次循环可执行的nextTick()事件的数目。


详情:process 进程 | Node.js API 文档

总结:

nextTick()的回调函数执行的优先级要高于setImmediate()。

process.nextTick()属于idle观察者,setImmediate()属于check观察者.在每一轮循环检查中,idle观察者先于I/O观察者,I/O观察者先于check观察者。

在具体实现上,process.nextTick()的回调函数保存在一个数组中,setImmediate()的结果则是保存在链表中。

在行为上,process.nextTick()在每轮循环中会将数组中的回调函数全部执行完,而setImmediate()在每轮循环中执行链表中的一个回调函数


5、第三方库 async.js

async.js是一个第三方库,带有很多api。

暴露了一个async对象,这个对象身上有很多的api(多任务执行),例如parallel,series等。

//和series/waterfall不同,task是并列执行的,callback不是执行下一个task。 
async.parallel([
    function(callback){
        callback(null,'任务1')
    },
    function(callback){
        callback(null,'任务2')
    },
],(err,data)=>{
    console.log('data',data)
})
//按顺序执行数组里的task,没有调用到callback不会执行下一个task
async.series([
    function(callback){
        // do some stuff ...
        callback(null, 'one');
    },
    function(callback){
        // do some more stuff ...
        callback(null, 'two');
    }
],
// optional callback
function(err, results){
    // results is now equal to ['one', 'two']
});

async.js更多详情:async-js - npm

8cd98e50679064252fff661a72fd66a0.jpg



相关文章
|
4月前
|
JSON 前端开发 安全
前端开发中的跨域解决方案探究
跨域是前端开发中常见的问题之一,本文将探讨跨域的概念、产生的原因,以及常见的解决方案,包括JSONP、CORS、代理等。通过本文的学习,读者可以深入了解跨域问题及解决方案,为自己的前端开发工作提供参考。
|
4月前
|
JSON 前端开发 安全
前端开发中的跨域问题及解决方案
在前端开发中,跨域是一个常见但又令人头疼的问题。本文将深入探讨跨域产生的原因以及一些常见的解决方案,帮助开发者更好地理解和处理跨域情况。
|
4月前
|
缓存 监控 前端开发
前端性能优化以及解决方案
前端性能优化关乎用户体验和网站竞争力,包括减少HTTP请求、使用CDN、压缩资源、延迟加载、利用浏览器缓存等策略。制定优化计划,使用监控工具,遵循最佳实践并持续学习,能提升网站速度和稳定性。
71 0
|
1月前
|
前端开发 测试技术 API
现代前端开发中的跨平台挑战与解决方案探讨
随着移动设备和桌面端用户体验的日益融合,现代前端开发面临着跨平台兼容性的重大挑战。本文将探讨这些挑战的根源,并介绍一些创新的解决方案,帮助开发人员更好地应对不同平台之间的差异,提升应用程序的用户体验和性能。
|
3月前
|
开发框架 前端开发 JavaScript
现代前端开发中的跨平台解决方案比较与应用
在现代软件开发中,跨平台解决方案成为了开发者们的热门话题。本文将探讨几种主流的跨平台开发框架及其特点,重点比较它们在前端开发中的应用场景和优劣势。通过对比分析,读者可以更好地理解如何选择适合自己项目需求的跨平台解决方案。
|
2月前
|
前端开发
纯前端模拟后端接口异步获取数据
纯前端模拟后端接口异步获取数据
32 0
|
3月前
|
前端开发
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
前端React篇之React setState 调用的原理、React setState 调用之后发生了什么?是同步还是异步?
|
4月前
|
前端开发
如何处理前端应用程序中的异步操作
前端异步操作常见方法包括回调函数、Promise 和 async/await。回调函数可能导致回调地狱,Promise 提供了更好的错误处理和链式调用,而 async/await 则基于 Promise,以同步风格处理异步任务,提高代码可读性。根据需求和喜好选择相应方法,以实现更可靠、易维护的代码。
|
4月前
|
前端开发 JavaScript UED
【Web 前端】异步函数
【5月更文挑战第1天】【Web 前端】异步函数
|
4月前
|
前端开发
前端性能优化:掌握解决方案
我们常说性能永远是第一需求,作为一个前端工程师,不管使用什么框架,不管从事什么类型的网站或应用开发,只要是项目被用户使用,性能优化就永远是你需要关注的问题。通常情况下,工程师们在深入了解前端技术的原理后,才能总结出性能优化的方案,需要多年经验的积累。前端技术日新月异,优秀的性能优化方案在近几年也层出不穷。本课程带你使用当今行业中非常前沿&专业的方案,解决前端性能优化问题。无论是为了解决工作中的实际问题,还是为了提升能力,这门课都能帮到你。
40 2
前端性能优化:掌握解决方案