前端大厂面试题探索编辑部——第四期

目录

题目

单选题

题解

JavaScript的异步编程

Promise

异步函数async/await

关于Ajax


题目

这期只有一道题,我们来详细讲讲JavaScript的异步编程,当然,异步编程是许多编程语言都有的一种编程思想,我们在前端这个领域,专注学清楚JavaScript和TypeScript就行。

单选题

6.考虑以下关于 JavaScript 异步编程的说法,哪个是正确的()

A. Promise 对象是一种代表异步操作最终完成或者失败的对象。

B. setTimeout 函数保证在设定的时间后立即执行回调函数。

C. async/await 可以用在普通函数中,不需要函数被声明为异步函数。

D. 在 JavaScript 中,Ajax操作都是非阻塞的。

题解

JavaScript的异步编程

要讲就细致一些讲吧,异步,有编程基础的会知道,我们可以不必等待一段代码执行完之后,再去执行下面的代码,如果在等待其他操作完成的同时,即使运行其他代码,系统也能保持稳定,那么我们务实一点来说,是可以选择异步编程这种思想的。JavaScript在设计之初,是一门单线程的语言,但是我们可以通过一些手段,来完成异步编程

Promise

JavaScript中的异步编程,绕不开Promise,国内可以翻译为"期约",但我觉得我们还是就称为Promise好一些。Promise是ECMAScript6新增的,Promise本身是一种类型,即引用类型,本质是个对象,可以通过new操作符来实例化,比如下面的代码。

javascript 复制代码
Let p = new Promise( () => {})
​
setTimeout(console.log, 0, p)

我在读《JavaScript高级程序设计》这本书的时候,书中向读者介绍了一种思想,就是我们可以把Promise看成一个状态机,书中直接就称其为期约状态机,主要有三种状态:待定(pending),兑现(fulfilled或resolved)和拒绝(rejected),Promise只可能是这三种状态,而且特别要注意的是:无论落定哪种状态都是不可逆的。同时,Promise的状态是私有的,JavaScript不能检测到其是哪种状态。

Promise既然是对象,那么它肯定有对应的方法,如前所述,我们说的待定状态有可能转换为兑现和拒绝这两种状态,控制Promise状态状态的转换是通过调用它的两个函数参数实现的,分别是resolve()和reject(),比如我们写下这样的代码,在浏览器中就会有这样的输出。

javascript 复制代码
let p1 = new Promise((resolve,reject) => resolve())
setTimeout(console.log,0,p1)

let p2 = new Promise((resolve,reject) => reject())
setTimeout(console.log,0,p2)

但回到这期的主题,异步编程,其实这部分代码并不是异步操作,我们来一个实际的例子,来说明Promise是如何完成异步操作的。

javascript 复制代码
function performAsyncTask() {
    return new Promise((resolve, reject) => {
        //我们使用setTimeout模拟异步操作,在2秒后执行
        setTimeout(() => {
            // 随机决定成功或失败
            const isSuccess = Math.random() > 0.5
            if (isSuccess) {
                // 操作成功
                resolve("成功")
            } else {
                // 操作失败
                reject("失败")
            }
        }, 2000)
    });
}

// 调用 performAsyncTask 并处理 Promise
performAsyncTask()
    .then(successMessage => {
        console.log(successMessage)
        // 成功处理逻辑
    })
    .catch(errorMessage => {
        console.error(errorMessage)
        // 失败处理逻辑
    })

我们通过定义一个函数performAsyncTask,这个函数中我们返回一个Promise对象实例,用setTimeout模拟异步操作,真正执行了异步编程的是调用performAsyncTask这一部分。Promise这个请求会在未来的某个时刻返回数据,要么成功,要么失败。

或许会有读者会提出这样的问题,我们声明一个自定义的对象,似乎也能完成这个操作?理论上是可以的,但别忘了,我们使用的resolve和reject方法,都是Promise对象已经有的方法,如果自定义对象,你还要自定义这些功能函数。通过前面的例子,其实选项A自然已经有答案了,Promise对象是一种代表异步操作最终完成或者失败的对象。Promise的优点在于它可以用一种链式结构,把多个异步操作串联起来

同时,这里我们也用到了setTimeout函数,正确的表述是:setTimeout保证的是,在设定的时间后,回调函数被添加到任务队列中,如果任务队列中已经有其他任务在等待,那么回调函数需要等待其他任务执行完毕之后才能执行

异步函数async/await

async/await是ES8规范新增的,这个异步函数的引入,让程序员可以以同步方式写的代码,能够异步执行。规范来讲,JavaScript的异步编程的方式只有两种:Promise和回调函数,async/await其实是基于Promise的更方便的方式,async/await都是关键字,所以其实这种一种编程方式。所以,使用了async/await关键字的函数,就是异步函数了,不再是普通函数了

比如这个例子,用async来表示这个函数是一个异步函数,我还是选择用Promise对象作为返回值,这样就表明了我们在使用异步编程,这里我就先简单的例子来。输出结果为3。

javascript 复制代码
async function f0() { 
 let a = new Promise((resolve, reject) => setTimeout(resolve, 1000, 3)); 
 console.log(await a); 
} 
fo()
关于Ajax

完整的Ajax的介绍,我就不详细讲了,后面我会专门出文章,讲一讲网络请求。我们需要记住的是:Ajax中的XMLHttpRequest是有同步和异步两种设置的,如果我们在open方法的参数中,设置为true,即异步的Ajax,那么它是阻塞的;而如果把参数设置为false,Ajax就是同步的,同步的Ajax就是非阻塞的。

相关推荐
xy345316 小时前
谷歌Lighthouse安装指南(Chrome扩展程序可视化操作)
前端·chrome·测试工具·lighthouse
乱码三千16 小时前
密码管理工具站正式上线啦
前端·html·github
IMPYLH17 小时前
HTML 的 <rt> 元素
前端·html
单线程_0117 小时前
从案例分析 Vue3 Tokenizer+Parser 源码五
前端·javascript·vue.js
mldong1 天前
你的 Vue3 项目也能有钉钉同款审批流设计器:npm 装包,10 分钟画出第一条审批流
前端·vue.js
2分钟速写快排1 天前
什么是 RAG?如何用 RAG 实现一个用户记忆?
前端·后端·ai编程
passerby60611 天前
如何自己造一个时间处理库
前端·javascript·github
走到天涯海角1 天前
react里面的长列表渲染优化
前端·react.js·前端框架
小羊没烦恼!1 天前
Hello Web API系列教程——Web API与国际化
java·服务器·前端·javascript·php
北岛贰1 天前
迷茫焦虑期,我做了一个带支付带官网的 AI 聊天虚拟恋人 App
前端·人工智能·后端