前端基础-异步3
3.7 Promise.all
参考答案:
Promise.all(iterable) 方法返回一个 Promise 实例,此实例在 iterable 参数内所有的 promise 都“完成(resolved)”或参数中不包含 promise 时回调完成(resolve);如果参数中 promise 有一个失败(rejected),此实例回调失败(reject),失败的原因是第一个失败 promise 的结果。
解析:
语法
Promise.all(iterable);
参数
iterable
一个可迭代对象,如
Array或String
返回值
- 如果传入的参数是一个空的可迭代对象,则返回一个已完成(already resolved)状态的
Promise - 如果传入的参数不包含任何
promise,则返回一个异步完成(asynchronously resolved)Promise。注意:Google Chrome 58 在这种情况下返回一个已完成(already resolved)状态的Promise。 - 其它情况下返回一个处理中(pending)的
Promise。这个返回的promise之后会在所有的promise都完成或有一个promise失败时异步地变为完成或失败。 见下方关于“Promise.all 的异步或同步”示例。返回值将会按照参数内的promise顺序排列,而不是由调用promise的完成顺序决定。
3.8 与promise.all相反的是哪一个
参考答案:
Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。
扩展:
语法
Promise.race(iterable);
参数
iterable
可迭代对象,类似
Array
返回值
一个待定的 Promise]只要给定的迭代中的一个promise解决或拒绝,就采用第一个promise的值作为它的值, 从而异步地解析或拒绝(一旦堆栈为空)。
3.9 promise实现文件读取
参考答案:
封装异步读取文件操作
- fs.readFile()方法用于异步读取文件(node核心模块)
- 将Promise的实例对象作为函数的返回值返回
- 这样函数执行完毕后就得到一个Promise对象的实例,可以通过.then方法传入成功的回调和失败的回调
const fs = require('fs');
const path = require('path');
function asyncGetFileByPath(p) {
return new Promise((resolve, reject) => {
// Promise对象里面的参数,会立即执行(前面说过)
fs.readFile(path.join(__dirname, p), 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
})
}
asyncGetFileByPath('./files/1.txt')
.then(
(data) => { // 成功的回调
console.log(data);
},
(err) => { // 失败的回调
console.error(err);
}
)


解决回调地狱
- 前面已经成功的封装了一个读取文件的函数
- 下面用它来体验一下读取多个文件
- 我们在.then()方法中,第一个参数resolve()方法中,返回一个promise对象B.
- 那么在执行.then()的resolve()方法完毕后,此时的执行环境是这个Promise的实例b
- 可以通过b的.then()方法继续传入resolve取消回调地狱,让代码趋于扁平化
const fs = require('fs');
const path = require('path');
function asyncGetFileByPath(p) {
return new Promise((resolve, reject) => {
// Promise对象里面的参数,会立即执行(前面说过)
fs.readFile(path.join(__dirname, p), 'utf-8', (err, data) => {
if (err) {
reject(err);
} else {
resolve(data);
}
})
})
}
asyncGetFileByPath('./files/1.txt')
.then(
(data) => { // 成功的回调 '1.txt'
console.log(data); // 打印出 1.txt 数据
return asyncGetFileByPath('./files/2.txt')
},
(err) => { // 失败的回调
console.error(err);
}
)
.then( // 成功的回调 '2.txt'
(data) => {
console.log(data); // 打印出 2.txt 中的数据
return asyncGetFileByPath('./files/3.txt') // 继续返回Promise对象的实例
},
(err) => {
console.error(err);
}
)
.then(
(data) => { // 成功的回调 '3.txt'
console.log(data); // 打印出 3.txt 中的数据
},
(err) => {
console.error(err);
}
)
3.10 用js实现sleep,用promise
参考答案:
function sleep(time) {
return new Promise(resolve => setTimeout(resolve, time))
}
const t1 = +new Date()
sleep(3000).then(() => {
const t2 = +new Date()
console.log(t2 - t1)
})
优点:这种方式实际上是用了 setTimeout,没有形成进程阻塞,不会造成性能和负载问题。
缺点:虽然不像 callback 套那么多层,但仍不怎么美观,而且当我们需要在某过程中需要停止执行(或者在中途返回了错误的值),还必须得层层判断后跳出,非常麻烦,而且这种异步并不是那么彻底,还是看起来别扭
3.11 实现一个 Scheduler 类,完成对Promise的并发处理,最多同时执行2个任务
参考答案:
class Scheduler {
constructor() {
this.tasks = [], // 待运行的任务
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
前端岗位面试真题宝典 文章被收录于专栏
本面试宝典均来自校招面试题目大数据进行的整理
查看1道真题和解析