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

目录

题目

单选题

题解

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操作符来实例化,比如下面的代码。

Let p = new Promise( () => {})
​
setTimeout(console.log, 0, p)

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

前端大厂面试题探索编辑部——第四期_第1张图片

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

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

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

前端大厂面试题探索编辑部——第四期_第2张图片

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

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这个请求会在未来的某个时刻返回数据,要么成功,要么失败。

前端大厂面试题探索编辑部——第四期_第3张图片前端大厂面试题探索编辑部——第四期_第4张图片

       或许会有读者会提出这样的问题,我们声明一个自定义的对象,似乎也能完成这个操作?理论上是可以的,但别忘了,我们使用的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。

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

你可能感兴趣的:(前端)