Promise的常见面试题

news2024/10/7 16:17:32

 四、相关面试题

1. 多个 .catch

var p = new Promise((resolve, reject) => {
  reject(Error('The Fails!'))
})

p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))

以上代码的输出将会是什么?

打印两次 The Fails!

解析:我们使用构造函数方法创建一个 Promise,并通过 reject 回调立即触发错误。然后 .catch 工作方式类似于 DOM 的 .addEventListener(event,callback) 或 Event Emitter 的 .on(event,callback),其中可以添加多个回调。每个都用同样的参数进行调用。

2. 多个 .catch

var p = new Promise((resolve, reject) => {
  return Promise.reject(Error('The Fails!'))
})

p.catch(error => console.log(error.message))
p.catch(error => console.log(error.message))

以上代码的输出将会是什么? 

解析:

使用 Promise 构造函数时,必须调用 resolve() 或 reject() 回调。 Promise 构造函数不使用你的返回值,因此实际上不会再收到由 Promise.reject() 创建的其他 Promise。

在 Promise.reject() 之后没有 .catch 时,答案是 UnhandledPromiseRejectionWarning

3、链接 .then 和 .catch

var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
  })
  .catch(error => console.log(error))
  .then(error => console.log(error))

以上代码的输出将会是什么?

打印错误和 undefined

解析:

当链接 .then 和 .catch 时,将它们视为一系列步骤会很有帮助。每个 .then 都接收前一个 .then 返回的值作为其参数。但是,如果你的 “step” 遇到错误,则任何后续的 .then “ steps” 都将被跳过,直到遇到 .catch。如果要覆盖错误,你要做的就是返回一个非错误值。可以通过任何随后的 .then 访问。

提示: console.log() 总是返回 undefined

4. 链接 .catch

var p = new Promise((resolve, reject) => {
    reject(Error('The Fails!'))
  })
  .catch(error => console.log(error.message))
  .catch(error => console.log(error.message))

以上代码的输出将会是什么? 

The Fails!

解析

当链接 .catch 时,每个仅处理先前的 .then 或 `.catch “步骤” 中引发的错误。在此例中,第一个 .catch 返回 console.log,只能通过在两个 .catch 之后添加 .then() 来访问。

5. 多个 .catch

new Promise((resolve, reject) => {
    resolve('Success!')
  })
  .then(() => {
    throw Error('Oh noes!')
  })
  .catch(error => {
    return "actually, that worked"
  })
  .catch(error => console.log(error.message))

以上代码的输出将会是什么?

不打印任何内容

提示: .catch可以简单地通过返回一个常规值来忽略(或覆盖)错误。

该技巧仅在随后的 .then 接收该值时有效。

6. .then 之间的流程

Promise.resolve('Success!')
  .then(data => {
    return data.toUpperCase()
  })
  .then(data => {
    console.log(data)
  })

以上代码的输出将会是什么?

SUCCESS!

提示:.then依次传递数据,从 return value 到下一个.then(value => /* handle value */)

为了将值传递给下一个 .thenreturn 是关键。

7. .then 之间的流程

Promise.resolve('Success!')
  .then(data => {
    return data.toUpperCase()
  })
  .then(data => {
    console.log(data)
    return data
  })
  .then(console.log)

以上代码的输出将会是什么?

打印 "SUCCESS!" 和 "SUCCESS!"

解析:

有两个 console.log 调用将被调用。

8. .then 之间的流程

Promise.resolve('Success!')
  .then(data => {
    data.toUpperCase()
  })
  .then(data => {
    console.log(data)
  })

以上代码的输出将会是什么?

打印 undefined

提示:.then 依次传递数据,从返回值到下一个 .then(value => /* handle value */)

为了将值传递给下一个 .thenreturn 是关键。

9. .then 和 .catch 之间的流程

Promise.resolve('Success!')
  .then(() => {
    throw Error('Oh noes!')
  })
  .catch(error => {
    return 'actually, that worked'
  })
  .then(data => {
    throw Error('The fails!')
  })
  .catch(error => console.log(error.message))

以上代码的输出将会是什么?

The fails!

10、基础输出题

以下代码最后输出什么?

      const promise = new Promise((resolve, reject) => {
        console.log(1)
        resolve()
        console.log(2)
      })
      promise.then(() => {
        console.log(3)
      })
      console.log(4)

1  2  4  3

记住 new Promise 里的参数函数,是同步被执行的,故而先输出 1,2,resolve 后还需要等待进入下一个事件循环。then 把参数函数推入微任务队列,并不直接执行。输出 4,接着事件循环进入下一轮,输出 3.

以下代码最后输出什么? 

        var promise = new Promise(function (resolve, reject) {
            setTimeout(function () {
                resolve(1);
            }, 3000)
        })
        
        // 打印结果是??
        promise
            .then(() => {
                return Promise.resolve(2)
            })
            .then(n => {
                console.log(n)
            })


        // 打印结果是??
        promise
            .then(() => {
                return 2
            })
            .then(n => {
                console.log(n)
            })


        // 打印结果是??
        promise.then(2).then(n => {
            console.log(n)
        })

输出2。Promise.resolve 就是一个 Promise 对象就相当于返回了一个新的 Promise 对象。然后在下一个事件循环里才会去执行 then

输出2。和上一点不一样的是,它不用等下一个事件循环。

输出1。then 和 catch 期望接收函数做参数,如果非函数就会发生 Promise 穿透现象,打印的是上一个 Promise 的返回。

 以下代码最后输出什么?

        const promise = new Promise((resolve, reject) => {
            resolve('success1');
            reject('error');
            resolve('success2');
        });

        promise
            .then((res) => {
                console.log('then: ', res);
            })
            .catch((err) => {
                console.log('catch: ', err);
            });

打印:then:  success1

牢牢记住 Promise 对象的状态只能被转移一次,resolve('success1') 时状态转移到了 fullfilled 。后面 reject 就调用无效了,因为状态已经不是 pending

以下代码最后输出什么? 

        Promise.resolve()
            .then(() => {
                return new Error('error!!!')
            })
            .then((res) => {
                console.log('then: ', res)
            })
            .catch((err) => {
                console.log('catch: ', err)
            })

没有抛出错误和异常,只是 return 了一个对象,哪怕他是 Error 对象,那自然也是正常走 then 的链式调用下去了,不会触发 catch 

以下代码最后输出什么?

const promise = new Promise((resolve, reject) => {
    console.log(1);
    resolve();
    console.log(2);
})
promise.then(() => {
    console.log(3);
})
console.log(4);

首先Promise新建后立即执行,所以会先输出1,2,而Promise.then()内部的代码在当次事件循环的结尾立即执行,所以会先输出4,最后输出3.
答案:1 2 4 3

 以下代码最后输出什么​​​​​​​?

Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)

Promise.resolve方法的参数如果是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为resolved,Promise.resolve方法的参数,会同时传给回调函数。
then方法接受的参数是函数,而如果传递的并非是一个函数,它实际上会将其解释为then(null),这就会导致前一个Promise的结果会传递下面。
答案 1

红灯3秒亮一次,绿灯1秒亮一次,黄灯2秒亮一次;如何让三个灯不断交替重复亮灯?(用Promise实现)三个亮灯函数已经存在:

function red() {
    console.log('red');
}
function green() {
    console.log('green');
}
function yellow() {
    console.log('yellow');
}

红灯3秒亮一次,绿灯1秒亮一次 ,黄灯2秒亮一次,意思就是3秒执行一次red函数,2秒执行一次green函数,1秒执行一次yellow函数,不断交替重复亮灯,意思就是按照这个顺序一直执行这3个函数,这步可以利用递归来实现。

function red() {
    console.log('red');
}
function green() {
    console.log('green');
}
function yellow() {
    console.log('yellow');
}

var light = function (timmer, cb) {
    return new Promise(function (resolve, reject) {
        setTimeout(function () {
            cb();
            resolve();
        }, timmer);
    });
};

var step = function () {
    Promise.resolve().then(function () {
        return light(3000, red);
    }).then(function () {
        return light(2000, green);
    }).then(function () {
        return light(1000, yellow);
    }).then(function () {
        step();
    });
}

step();

实现mergePromise函数,把传进去的数组按顺序先后执行,并且把返回的数据先后放到数组data中。

const timeout = ms => new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve();
    }, ms);
});

const ajax1 = () => timeout(2000).then(() => {
    console.log('1');
    return 1;
});

const ajax2 = () => timeout(1000).then(() => {
    console.log('2');
    return 2;
});

const ajax3 = () => timeout(2000).then(() => {
    console.log('3');
    return 3;
});

const mergePromise = ajaxArray => {
    // 在这里实现你的代码

};

mergePromise([ajax1, ajax2, ajax3]).then(data => {
    console.log('done');
    console.log(data); // data 为 [1, 2, 3]
});

// 要求分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]

因为对于异步函数来说,并不会按顺序执行完一个,再执行后一个。
这道题主要考察用Promise控制异步流程,让这些函数一个执行完,再执行下一个。

      const timeout = ms =>
        new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve()
          }, ms)
        })

      const ajax1 = () =>
        timeout(2000).then(() => {
          console.log('1')
          return 1
        })

      const ajax2 = () =>
        timeout(1000).then(() => {
          console.log('2')
          return 2
        })

      const ajax3 = () =>
        timeout(2000).then(() => {
          console.log('3')
          return 3
        })

      const mergePromise = ajaxArray => {
        // 保存数组中的函数执行后的结果
        var arr = []
        // Promise.resolve方法调用时不带参数,直接返回一个resolved状态的 Promise 对象
        var resolved = Promise.resolve()
        ajaxArray.forEach(item => {
          resolved = resolved.then(item).then(res => {
            // 第一次的 then 方法用来执行数组中的每个函数,
            // 第二次的 then 方法接受数组中的函数执行后返回的结果,
            // 并把结果添加到 data 中,然后把 data 返回。
            arr.push(res)
            return arr
          })
        })
        // 遍历结束后,返回一个 Promise,也就是 resolved, 他的 [[PromiseValue]] 值就是 arr
        // 而 data(保存数组中的函数执行后的结果) 也会作为参数,传入下次调用的 then 方法中。
        return resolved
      }

      mergePromise([ajax1, ajax2, ajax3]).then(data => {
        console.log('done')
        console.log(data)
      })

      // 要求分别输出
      // 1
      // 2
      // 3
      // done
      // [1, 2, 3]

 以下代码最后输出什么​​​​​​​?

const first = () => (new Promise((resolve, reject) => {
    console.log(3);
    let p = new Promise((resolve, reject) => {
        console.log(7);
        setTimeout(() => {
            console.log(5);
            resolve(6);
        }, 0)
        resolve(1);
    });
    resolve(2);
    p.then((arg) => {
        console.log(arg);
    });

}));

first().then((arg) => {
    console.log(arg);
});
console.log(4);

这道题主要理解js执行机制
第一轮事件循环
先执行宏任务,主script,new Promise立即执行,输出 3,
执行p这个new Promise操作,输出 7,
发现setTimeout,将回调函数放入下一轮任务队列(Event Quene),p的then,暂且命名为then1,放入微任务队列,且first也有then,命名为then2,放入微任务队列。执行console.log(4),输出 4,宏任务执行结束。
再执行微任务,执行then1,输出 1,
执行then2,输出 2.
第一轮事件循环结束,开始执行第二轮。
第二轮事件循环
先执行宏任务里面的,也就是setTimeout的回调,输出 5.
resolve(6)不会生效,因为p的Promise状态一旦改变就不会再变化了。
答案 3 7 4 1 2 5

有8个图片资源的url,已经存储在数组urls中(即urls=['http://example.com/1.jpg',...,'http:''example.com/8.jpg']),而且已经有一个函数function loading,输入一个url链接,返回一个Promise,该Promise在图片下载完成的时候resolve,下载失败则reject。
但有一个要求,任何时刻同时下载的链接数量不可以超过3个。
请写一段代码实现这个需求,要求尽可能快速地将所有图片下载完成。

var urls = ['https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg', 'https://www.kkkk1000.com/images/getImgData/gray.gif', 'https://www.kkkk1000.com/images/getImgData/Particle.gif', 'https://www.kkkk1000.com/images/getImgData/arithmetic.png', 'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif', 'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg', 'https://www.kkkk1000.com/images/getImgData/arithmetic.gif', 'https://www.kkkk1000.com/images/wxQrCode2.png'];
function loadImg(url) {
    return new Promise((resolve, reject) => {
        const img = new Image()
        img.onload = function () {
            console.log('一张图片加载完成');
            resolve();
        }
        img.onerror = reject
        img.src = url
    })
};

解析
题目的意思是需要先并发请求3张图片,当一张图片加载完成后,又会继续发起一张图片的请求,让并发数保持在3个,直到需要加载的图片都全部发起请求。
用Promise来实现就是,先并发请求3个图片资源,这样可以得到3个Promise,组成一个数组promises,然后不断调用Promise.race来返回最快改变状态的Promise,然后从数组promises中删掉这个Promise对象,再加入一个新的Promise,直到全部的url被取完,最后再使用Promise.all来处理一遍数组promises中没有改变状态的Promise
答案:

      var urls = [
        'https://www.kkkk1000.com/images/getImgData/getImgDatadata.jpg',
        'https://www.kkkk1000.com/images/getImgData/gray.gif',
        'https://www.kkkk1000.com/images/getImgData/Particle.gif',
        'https://www.kkkk1000.com/images/getImgData/arithmetic.png',
        'https://www.kkkk1000.com/images/getImgData/arithmetic2.gif',
        'https://www.kkkk1000.com/images/getImgData/getImgDataError.jpg',
        'https://www.kkkk1000.com/images/getImgData/arithmetic.gif',
        'https://www.kkkk1000.com/images/wxQrCode2.png'
      ]
      function loadImg(url) {
        return new Promise((resolve, reject) => {
          const img = new Image()
          img.onload = function() {
            console.log('一张图片加载完成')
            resolve()
          }
          img.onerror = reject
          img.src = url
          console.log(img.src)
        })
      }

      function limitLoad(urls, handler, limit) {
        // 对数组做一个拷贝
        const urlArr = [].concat(urls)
        let promises = []

        //并发请求到最大数
        promises = urlArr.splice(0, limit).map((url, index) => {
          // 这里返回的 index 是任务在 promises 的脚标,用于在 Promise.race 之后找到完成的任务脚标
          return handler(url).then(() => {
            console.log(index)
            return index
          })
        })

        console.log(promises)

        // 利用数组的 reduce 方法来以队列的形式执行 last?
        return urlArr
          .reduce((last, url, currentIndex) => {
            return last
              .then(() => {
                // 返回最快改变状态的 Promise
                return Promise.race(promises)
              })
              .catch(err => {
                // 这里的 catch 不仅用来捕获 前面 then 方法抛出的错误
                // 更重要的是防止中断整个链式调用
                console.error(err)
              })
              .then(res => {
                // 用新的 Promise 替换掉最快改变状态的 Promise
                promises[res] = handler(urlArr[currentIndex]).then(() => {
                  return res
                })
              })
          }, Promise.resolve())
          .then(() => {
            return Promise.all(promises)
          })
      }

      limitLoad(urls, loadImg, 3)
      // 因为 limitLoad 函数也返回一个 Promise,所以当 所有图片加载完成后,可以继续链式调用
      // limitLoad(urls, loadImg, 3).then(() => {
      //     console.log('所有图片加载完成');
      // }).catch(err => {
      //     console.error(err);
      // })



封装一个异步加载图片的方法

      function loadImgAsync(url) {
        return new Promise(function(resolve, reject) {
          var img = new Image()
          img.onload = function() {
            resolve(img)
          }
          img.onerror = function() {
            reject(new Error('无法加载该路径图片' + url))
          }
          img.src = url
        })
      }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/716164.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

纯粹数学作业

1、列举一个真命题、一个假命题、一个不知道真假的命题、一个不是命题的陈述。 真命题:太阳是发光发热的。 同位角相等,两直线平行。 假命题:三角形的三个内角和不是180 不知真假的命题:树叶是黄色的。 不是命题的陈述&#x…

伦敦银实时行情软件日常使用

目前伦敦金市场上很多交易都是通过MT4平台来完成,这个行情软件的优势,除了操作简洁、分析功能全面和交易稳定外,支持不同的手机和电子设备版本也是很重要的一点。但很多用户,特别是对于新手日常在操作的过程中,都会或多…

jdk1.8官网下载

地址: https://www.oracle.com/java/technologies/downloads/#java8 选linux x86位的:

【C语言】从水仙花构建思维

前言 🎈大家好,我是何小侠🎈 🍃大家可以叫我 小何或者小侠 🍃 💐希望能通过写博客加深自己对于学习内容的理解💐 🌸也能帮助更多人理解和学习🌸 击石乃有火,…

【反图+拓扑排序】ABC245 F

F - Endless Walk (atcoder.jp) 题意: 思路: 首先,我们什么时候需要建反图:在一个有向图中,我们需要找出可以到达指定的结点的结点时,我们可以建立反图 这道题中,我们需要找出所有能够到达环…

剑指offer刷题笔记--Num31-40

1--栈的压入、弹出序列(31) 直观思路:用两个指针 i 和 j 指向压入和弹出的 vector,终止条件是:所有元素都压入了辅助栈(i > len),且辅助栈当前的栈顶元素与弹出的元素 popped[j] …

Maven Snapshot 更新策略配置方法

项目场景: 提示:这里简述项目相关背景: 在微服务的项目开发中,特别是更新比较频繁的项目,经常会遇到一些项目依赖的问题,依赖的一个项目经常更新,所以我下拉更新项目时候经常出现代码不一致&a…

Ansys Zemax | 使用软件建立立方体卫星系统(一)

在航空航天工业领域中,立方体卫星(CubeSats)已然是一种低成本、易制造的航天光学系统的解决方案。通过制造一组更小、更实惠的系统,使得为航天产品开发生产线方法成为可能。 立方体卫星光学系统的制造商们需要一个准确并可靠的方法…

基于微信小程序学校部门年终绩效考核自动评分系统(源码+文档+数据库+PPT)

基于微信小程序的部门年终绩效考核系统,为加强学校运营队伍建设提高学校管理力,合理评价教师及部门年度工作计划完成情况,促进整体绩效改进,鼓励管理团队注重对下属进行帮助、提升,促进团队扩张和发展,特制…

【花雕】全国青少年机器人技术一级考试备考实操搭建手册10

随着科技的不断进步,机器人技术已经成为了一个重要的领域。在这个领域中,机械结构是机器人设计中至关重要的一部分,它决定了机器人的形态、运动方式和工作效率。对于青少年机器人爱好者来说,了解机械结构的基础知识,掌…

idea篇2:常用插件

1、汉化插件 下载完成后点击Restart IDE 如果你这边插件搜不出来,还可以去官网插件地址下载 打开 https://plugins.jetbrains.com/ 然后点击Instatll To IDE 弹出Success的时候我们切换回IDEA,然后点击ok 如果你这种方式还是无法成功 那么还可以点击插件商城的Ve…

半年面试数百场,我总结出了这份 10w 字 Java 面试复盘笔记

Java 面试 Java 作为编程语言中的 NO.1,选择入行做 IT 做编程开发的人,基本都把它作为首选语言,进大厂拿高薪也是大多数小伙伴们的梦想。以前 Java 岗位人才的空缺,而需求量又大,所以这种人才供不应求的现状,就是 Java 工程师的薪…

【javascript】导航栏

要实现这样的效果主要有两点。第一&#xff0c;当鼠标经过主导航栏里面的内容就会被放大&#xff0c;鼠标离开后就会恢复原来的样子&#xff1b;第二&#xff0c;当鼠标经过主导航时对应的副导航的内容就会呈现。 <!DOCTYPE html> <html lang"en"> <…

Flink写入数据到ClickHouse

文章目录 1.ClickHouse建表1.ClickHouse依赖2.Bean实体类3.ClickHouse业务写入逻辑4.测试写入类5.发送数据 1.ClickHouse建表 ClickHouse中建表 CREATE TABLE default.test_write (id UInt16,name String,age UInt16 ) ENGINE TinyLog();1.ClickHouse依赖 Flink开发相关…

爬虫入门指南(7):使用Selenium和BeautifulSoup爬取豆瓣电影Top250实例讲解【爬虫小白必看】

文章目录 介绍技术要点SeleniumBeautifulSoupOpenpyxl 实现步骤&#xff1a;导入所需库设置网页URL和驱动路径创建 ChromeDriver 服务配置 ChromeDriver创建 Excel 文件爬取数据关闭浏览器保存 Excel 文件 完整代码导出的excel 效果图未完待续.... 介绍 在本篇博客中&#xff…

Day976.如何安全、快速地接入OAuth 2.0? -OAuth 2.0

如何安全、快速地接入OAuth 2.0&#xff1f; Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于如何安全、快速地接入OAuth 2.0&#xff1f;的内容。 授权服务将 OAuth 2.0 的复杂性都揽在了自己身上&#xff0c;这也是授权服务为什么是 OAuth 2.0 体系的核心的原因之…

企业为什么纷纷推崇数字化管理?

企业提倡或推崇数字化管理&#xff0c;通常是因为几个原因&#xff1a; 效率和生产力&#xff1a;数字管理系统简化流程并自动执行重复任务&#xff0c;从而提高效率和生产力。数字工具可以更快地输入、检索和分析数据&#xff0c;减少人工工作和人为错误。这种效率使企业能够在…

STM32速成笔记—Flash闪存

文章目录 一、Flash简介二、STM32F1的Flash三、Flash操作步骤四、程序设计4.1 读取数据4.2 写入数据&#xff08;不检查&#xff09;4.3 写入数据&#xff08;检查&#xff09; 五、注意事项 一、Flash简介 快闪存储器&#xff08;flash memory&#xff09;&#xff0c;是一种…

物理与IP环境的重要性:打造稳定可靠的亚马逊测评环境

在亚马逊平台上进行测评补单、撸卡和撸货等活动&#xff0c;首要问题是确保环境的安全性和稳定性。一个稳定的环境是进行测评和撸卡的基础&#xff0c;如果无法解决安全性问题&#xff0c;那么从事这些项目就不值得。在环境技术研发领域已经有六七年的经验&#xff0c;在早期测…

红利期已过?2023跨境电商还吃香吗?亚马逊还能做吗?

2022年&#xff0c;由于疫情反复和外部因素的影响&#xff0c;跨境电商的情况并不乐观。但这并不意味着跨境电商已经走到了绝境。随着贸易全球化的深入发展&#xff0c;平台规则不断完善&#xff0c;国家相继出台最新的扶持政策&#xff0c;为跨境电商企业带来了更多的发展机遇…