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

目录

题目

单选题

题解

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就是非阻塞的。

相关推荐
吕彬-前端14 分钟前
使用vite+react+ts+Ant Design开发后台管理项目(五)
前端·javascript·react.js
学前端的小朱16 分钟前
Redux的简介及其在React中的应用
前端·javascript·react.js·redux·store
guai_guai_guai25 分钟前
uniapp
前端·javascript·vue.js·uni-app
bysking1 小时前
【前端-组件】定义行分组的表格表单实现-bysking
前端·react.js
王哲晓2 小时前
第三十章 章节练习商品列表组件封装
前端·javascript·vue.js
fg_4112 小时前
无网络安装ionic和运行
前端·npm
理想不理想v2 小时前
‌Vue 3相比Vue 2的主要改进‌?
前端·javascript·vue.js·面试
酷酷的阿云2 小时前
不用ECharts!从0到1徒手撸一个Vue3柱状图
前端·javascript·vue.js
微信:137971205872 小时前
web端手机录音
前端
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb