promise面试必刷笔试题

本文深入探讨了Promise在JavaScript中的作用,如何优雅处理异步代码,避免回调地狱。介绍了Promise的状态变化、回调机制,以及Promise.all、Promise.race、Promise.resolve和Promise.reject的使用。此外,还列举了Promise面试中常见的笔试题,包括处理异步操作、错误处理和并行执行等场景,旨在帮助读者更好地理解和应用Promise。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Promise 是 JavaScript 中一种用于处理异步操作的对象,它可以让我们更优雅地处理异步代码,并解决了回调地狱(callback hell)的问题。Promise 是一个代表了异步操作最终完成或失败的对象,并可以获取异步操作的结果。

Promise 的原理是基于状态(state)和回调函数(callback)的机制:

  1. 状态:Promise 有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。初始状态是 pending,当异步操作完成后,可以变为 fulfilled(成功)或 rejected(失败),一旦状态发生变化,就不可再改变。

  2. 回调函数:Promise 实例有两个回调函数:成功时的回调函数 then 和失败时的回调函数 catch。当异步操作成功时,会调用 then 方法指定的回调函数,传递成功的结果;当异步操作失败时,会调用 catch 方法指定的回调函数,传递失败的原因。

下面是一个简单的 Promise 示例:

// 异步操作函数
function asyncOperation() {
  return new Promise((resolve, reject) => {
    // 模拟异步操作
    setTimeout(() => {
      const random = Math.random();
      if (random < 0.5) {
        resolve("Success: " + random);
      } else {
        reject("Error: " + random);
      }
    }, 1000);
  });
}

// 调用异步操作函数
asyncOperation()
  .then((result) => {
    console.log(result); // 输出成功结果
  })
  .catch((error) => {
    console.error(error); // 输出失败原因
  });

在这个示例中,asyncOperation 函数返回一个 Promise 对象,当异步操作完成后,根据结果调用 resolvereject。然后我们通过 then 方法来处理成功的结果,通过 catch 方法来处理失败的原因。

Promise 的应用包括但不限于:

  • 异步操作:Promise 可以处理异步代码,让代码更具可读性和可维护性。
  • 多个异步操作的并行执行和串行执行:通过 Promise 的链式调用和 Promise.allPromise.race 方法可以实现多个异步操作的并行执行或串行执行。
  • 解决回调地狱:Promise 可以避免回调地狱,使代码结构更清晰、简洁。
  • 资源加载和错误处理:Promise 可以用于异步加载资源(例如图片、脚本等)以及错误处理。

Promise 对象有一些常用的静态方法,可以用于处理多个 Promise 实例,或者用于生成新的 Promise 实例。以下是一些常用的 Promise 静态方法:

1. Promise.all(iterable)

Promise.all 方法接收一个可迭代的对象(通常是一个数组),并返回一个新的 Promise 实例。该 Promise 实例在可迭代对象中所有的 Promise 实例都已解析(resolved)或其中任何一个 Promise 实例被拒绝(rejected)时才会解析或拒绝。

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise.all([promise1, promise2, promise3])
  .then(values => {
    console.log(values); // 输出:[1, 2, 3]
  });

2. Promise.race(iterable)

Promise.race 方法同样接收一个可迭代的对象,并返回一个新的 Promise 实例。该 Promise 实例解析或拒绝,取决于可迭代对象中第一个解析或拒绝的 Promise 实例。

const promise1 = new Promise(resolve => setTimeout(resolve, 100, 'one'));
const promise2 = new Promise(resolve => setTimeout(resolve, 200, 'two'));

Promise.race([promise1, promise2])
  .then(value => {
    console.log(value); // 输出:'one'
  });

3. Promise.resolve(value)

Promise.resolve 方法返回一个已解析的 Promise 实例,根据提供的值。如果提供的值是一个 Promise,则返回该 Promise 实例;如果提供的是一个 thenable 对象(拥有 then 方法的对象),则返回一个新的 Promise 实例,该实例的状态会根据 thenable 对象的状态而变化;其他情况下,返回一个以提供的值解析为成功状态的 Promise 实例。

const promise = Promise.resolve('Success');
promise.then(value => {
  console.log(value); // 输出:'Success'
});

4. Promise.reject(reason)

Promise.reject 方法返回一个被拒绝的 Promise 实例,给定一个拒绝原因(通常是一个 Error 对象)。

const reason = new Error('Something went wrong');
const promise = Promise.reject(reason);

promise.catch(error => {
  console.error(error.message); // 输出:'Something went wrong'
});

总结:promise的静态方法,all和any的用法区别:
Promise.all(),返回全部promise的返回值,有一个reject就不返回,也就是有一个拒绝就拒绝。
Promise.any(),返回单个promise,第一个resolve的值,所有都拒绝时才会都拒绝。

以下是一些与 Promise 相关的常见笔试题:

1. 理解 Promise 状态变化:

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Success");
  }, 1000);
});

console.log(promise); // 输出什么?

2. 使用 Promise 处理异步操作:

function fetchData() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Data fetched successfully");
    }, 2000);
  });
}

fetchData().then((data) => {
  console.log(data); // 输出什么?
});

3. 处理 Promise 的错误:

function asyncOperation() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject("Error occurred");
    }, 1000);
  });
}

asyncOperation().then((result) => {
  console.log(result);
}).catch((error) => {
  console.error(error); // 输出什么?
});

4. 处理多个 Promise 的并行执行:

const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise 1 resolved");
  }, 1000);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("Promise 2 resolved");
  }, 2000);
});

Promise.all([promise1, promise2]).then((values) => {
  console.log(values); // 输出什么?
});

5. Promise 的链式调用:

function asyncOperation() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve("Async operation completed");
    }, 1000);
  });
}

asyncOperation().then((result) => {
  console.log(result); // 输出什么?
  return "Next operation";
}).then((result) => {
  console.log(result); // 输出什么?
});

以上是一些常见的 Promise 相关的笔试题,通过理解和回答这些题目,可以加深对 Promise 的理解和应用。接下来稍微加点难度,继续做以下笔试题,

//1.同时调用resolve和reject会怎么样?
const promise = new Promise((resolve, reject) => {
    resolve();
    reject();
  });
//正确答案是fullfilled状态。promise一旦从pending状态转换到另一种状态就不可以再改变了,因此示例中
//先被转换成了fullfilled状态,再调用reject就不会被更改为reject状态了。

//2.promise数组串行执行

//用await
const requestAry = [() => api.request1(), () => api.request2(), () => api.request3()];

for (const requestItem of requestAry) {
  await requestItem();
}

//用then函数来串联多个promise
const finallyPromise = requestAry.reduce(
    (currentPromise, nextRequest) => currentPromise.then(() => nextRequest()),
    Promise.resolve() // 创建一个初始promise,用于链接数组内的promise
);

  Promise.resolve().then(() => {
    console.log(1);
  });
  await console.log(3);
  console.log(2);

  //输出:3 1 2


//promise的then的第二个回调函数和catch在请求出错时都会被触发,
//咋一看没什么区别啊,但其实,前者不能捕获当前then第一个回调函数中抛出的错误,但catch可以。

Promise.resolve().then(
    () => {
      throw new Error('来自成功回调的错误');
    },
    () => {
      // 不会被执行
    }
  ).catch(reason => {
    console.log(reason.message); // 将打印出"来自成功回调的错误"
  });
  
//then/catch/finally三个函数都会返回一个新的promise包装对象,
//被包装的值为被执行的回调函数的返回值,回调函数抛出错误则会包装一个rejected状态的promise。

// then函数
Promise.resolve().then(() => 1); // 返回值为 new Promise(resolve => resolve(1))
Promise.resolve().then(() => Promise.resolve(2)); // 返回 new Promise(resolve => resolve(Promise.resolve(2)))
Promise.resolve().then(() => {
  throw new Error('abc')
}); // 返回 new Promise(resolve => resolve(Promise.reject(new Error('abc'))))
Promise.reject().then(() => 1, () => 2); // 返回值为 new Promise(resolve => resolve(2))

// catch函数
Promise.reject().catch(() => 3); // 返回值为 new Promise(resolve => resolve(3))
Promise.resolve().catch(() => 4); // 返回值为 new Promise(resolve => resolve(调用catch的promise对象))

// finally函数
// 以下返回值均为 new Promise(resolve => resolve(调用finally的promise对象))
Promise.resolve().finally(() => {});
Promise.reject().finally(() => {});


//promise实现koa2洋葱中间件模型,
//可以让你的请求像剥洋葱一样,一层层进入再反向一层层出来,从而实现对请求统一的前后置处理。
const app = new Koa();
app.use(async (ctx, next) => {
  console.log('a-start');
  await next();
  console.log('a-end');
});
app.use(async (ctx, next) => {
  console.log('b-start');
  await next();
  console.log('b-end');
});

app.listen(3000);
//a-start -> b-start -> b-end -> a-end

请写出下面代码的运行结果,考察promise的执行顺序

const promise4 = new Promise((resolve, reject) => {
    Math.random() > 0.5 ? resolve(1) : reject(-1);
  }).then(
    res => console.log(res),
    err => console.log(err),
  )
try{
  const promise3 = new Promise((resolve, reject) => {
       reject(-1);
    }).then(
      res => console.log(res.a.a,'res')
    ).catch(e=>{
      console.log(res.a,'res')
      console.log(333333)
    })
}catch(e){
  console.log(222222)
}
const promise2 = new Promise((resolve,reject)=>{
    resolve('2222')
    reject('666')
    throw error('throw')
    console.log('33333')
}).then(res=>{
    throw error('throw')
    console.log('then')
}).then(res=>{
    console.log(9999)
})
.catch(e=>{
    console.log('catch')
}).finally(e=>{
    console.log(0)
})
const promise2222 = new Promise((resolve,reject)=>{
    resolve(2)
    console.log('33333')
}).then(res=>{
    throw error('throw')
    console.log('then')
}).then(res=>{
    console.log(9999)
}).catch(e=>{
    console.log('catch')
}).finally(e=>{
    console.log(0)
})

手写一个promise-retry

Promise.prototype.retry = function(cb,time){
    return new Promise((resolve,reject)=>{
        cb().then(res=>{
            resolve(res)
        }).catch(err=>{
            if(time>0){
                return Promise.retry(cb,time--)
            }else{
                reject('重试完毕,依然失败')
            }
        })
    })
}

最后也是全文最重要的,码字不易,欢迎点赞收藏加关注,你的鼓励,是我码字的动力,感谢感谢感谢!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

为了WLB努力

给点小钱,你的鼓励是我坚持动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值