阅读 55

Promise答题纪要(event loop)

Promise的几道基础题

const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
})
console.log('1', promise1);
//promise1 1 promise1实例

1.new 的时候就已经开始执行

如果出现下面这种被
const fn = () => (new Promise((resolve, reject) => {
  console.log(1);
  resolve('success')
}))
fn().then(res => {
  console.log(res)
})
console.log('start')


复制代码
const promise = new Promise((resolve, reject) => {
  console.log(1);
  resolve('success')
  console.log(2);
});
promise.then(() => {
  console.log(3);
});
console.log(4);

//1 2 4 3

2.resolve('success')这一步会把状态改成resolved,并把success这个值保存下来,如何继续执行同步任务,then后面是微任务
复制代码
const promise = new Promise((resolve, reject) => {
  console.log(1);
  console.log(2);
});
promise.then(() => {
  console.log(3);
});
console.log(4);

// 1 2 4

3.如果Promise没有resolve或者reject时,promise.then()里面的代码不会被执行,它只有在状态被改变之后才会执行!
复制代码
new Promise((resolve, reject) => {
  return resolve(1);
  // 后面的语句不会执行
  console.log(2);
})
 //返回一个Promise对象 并保存了resolved的值
 
4.当出现resolve一个数值或者没有then的时候会返回一个promise对象并把resolve里面的参数传递过去
复制代码
Promise.resolve(1)
  .then(2)
  .then(Promise.resolve(3))
  .then(console.log)
  // 打印出1 并返回了一个PromiseResult为undefined的promise对象
  
  Promise.resolve(1)
  .then(function(){return 2})
  .then(Promise.resolve(3))
  .then(console.log)
  // 2
  
  Promise.resolve(1)
  .then(function(){return 2})
  .then(function(){return Promise.resolve(3)})
  .then(console.log)
  // 3
  5. .then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。Promise方法链通过return传值,没有return就只是相互独立的任务而已
复制代码
const promise1 = new Promise((resolve, reject) => {
  console.log('promise1')
  resolve('resolve1')
})
const promise2 = promise1.then(res => {
  console.log(res)
})
console.log('1', promise1);
console.log('2', promise2);

/*
'promise1'
'1' Promise{<resolved>: 'resolve1'}
'2' Promise{<pending>}
'resolve1'
*/

6.new执行打印出promise1,resolve('resolve1')改状态,保存值,then为微任务,再继续执行同步代码和then
复制代码

Promise结合setTimeout

const promise = new Promise((resolve, reject) => {
  console.log(1);
  setTimeout(() => {
    console.log("timerStart");
    resolve("success");
    console.log("timerEnd");
  }, 0);
  console.log(2);
});
promise.then((res) => {
  console.log(res);
});
console.log(4);

//1 2 4 timerStart timerEnd success

7.定时器是宏任务在微任务之后执行,timerStart timerEnd为定时器里面的同步代码,resolve("success")保存值,then微任务
复制代码
例1:
setTimeout(() => {
  console.log('timer1');
  setTimeout(() => {
    console.log('timer3')
  }, 0)
}, 0)
setTimeout(() => {
  console.log('timer2')
}, 0)
console.log('start')
 
 // start timer1 timer2 timer3
 
 例2:
 setTimeout(() => {
  console.log('timer1');
  Promise.resolve().then(() => {
    console.log('promise')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
}, 0)
console.log('start')

//start timer1 promise timer2

8.两者一个是定时器,一个是Pomise.then ;可以理解为定时器是宏任务会被加入到下一轮宏仁务中,Pomise.then是微任务会被加入到本轮的微任务中
复制代码

Promise中的then、catch、finally

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
9.构造函数中的 resolve 或 reject 只有第一次执行有效,多次调用没有任何作用 。Promise的状态一经改变就不能再改变
复制代码
const promise = new Promise((resolve, reject) => {
  reject("error");
  resolve("success2");
});
promise
.then(res => {
    console.log("then1: ", res);
  }).then(res => {
    console.log("then2: ", res);
  }).catch(err => {
    console.log("catch: ", err);
  }).then(res => {
    console.log("then3: ", res);
  })

//catch:error then3: undefined
10.如9所述,当前Promise状态被改成rejected,后面的resolve不会再执行,所以可以得到catch:error;至于会打印出then3: undefined是因为.then和.catch都会返回一个新的Promise,且由于这个Promise没有返回值,所以打印出来的是undefined
复制代码
Promise.resolve(1)
  .then(res => {
    console.log(res);
    return 2;
  })
  .catch(err => {
    console.log(err);
    return 3;
  })
  .then(res => {
    console.log(res);
  });

// 1 2
11.在Promise中,返回任意一个非 promise 的值都会被包裹成 promise 对象,例如return 2会被包装为return Promise.resolve(2);且Promise可以链式调用,resolve(1)走的是第一个then,resolve(2)走的是第二个then

改成Promise.reject(1)也一样,上题会打印出1和3 ,return 3还是会包装成return Promise.resolve(3)

Promise.resolve().then(() => {
  return new Error('error!!!')
}).then(res => {
  console.log("then: ", res)
}).catch(err => {
  console.log("catch: ", err)
})
 
//return new Error('error!!!')也被包裹成了return Promise.resolve(new Error('error!!!'))
如果想抛出错误的话可以使用:
return Promise.reject(new Error('error'))或者throw new Error('error')
复制代码
const promise = Promise.resolve().then(() => {
  return promise;
})
promise.catch(console.err)

12..then 或 .catch 返回的值不能是 promise 本身,否则会造成死循环
复制代码
Promise.reject('err!!!')
  .then((res) => {
    console.log('success', res)
  }, (err) => {
    console.log('error', err)
  }).catch(err => {
    console.log('catch', err)
  })

// 'error' 'error!!!'
13.then有两个参数分别处理成功Promise.resolve()和失败的函数Promise.reject,现在是进入到then的第二个参数里面,这时代码不会执行,去掉第二个参数的话会进入到catch里面

还有另外一种情况:
Promise.resolve()
  .then(function success (res) {
    throw new Error('error!!!')
  }, function fail1 (err) {
    console.log('fail1', err)
  }).catch(function fail2 (err) {
    console.log('fail2', err)
  })
因为调用的是resolve()所以会进入到success函数,不会进入到fail1,这时success函数抛出了一个错误会被catch捕获到
复制代码
function promise1 () {
  let p = new Promise((resolve) => {
    console.log('promise1');
    resolve('1')
  })
  return p;
}
function promise2 () {
  return new Promise((resolve, reject) => {
    reject('error')
  })
}
promise1()
  .then(res => console.log(res))
  .catch(err => console.log(err))
  .finally(() => console.log('finally1'))

promise2()
  .then(res => console.log(res))
  .catch(err => console.log(err))
  .finally(() => console.log('finally2'))

// promise1 1 error finally1 finally2

14. promise1()执行完同步代码打印出promise1,resolve('1')改状态存值;then微任务1;finally()得等then执行完才会执行;执行promise2(),没有同步任务,catch微任务2,finally()得等catch执行完才会执行
复制代码

async/await的几道题

async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
  })
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

15. await后面的promise没有返回值没有改变状态,一直在pending中,所以一直await使得后面的代码不会被执行,同样then后面也不会执行
复制代码
async function async1 () {
  console.log('async1 start');
  await new Promise(resolve => {
    console.log('promise1')
    resolve('promise1 resolve')
  }).then(res => console.log(res))
  console.log('async1 success');
  return 'async1 end'
}
console.log('srcipt start')
async1().then(res => console.log(res))
console.log('srcipt end')

//  srcipt start
    async1 start
    promise1
    srcipt end
    promise1 resolve
    async1 success
    async1 end
    
16.console.log('async1 success')被放在await语法糖生成的Promise.then里了,而await的等待必须要等后面Promise.then之后才会结束.
在async1中的new Promise它的resovle的值和async1().then()里的值是没有关系的.
async 函数会返回一个 Promise 对象,如果在函数中 return 一个直接量(普通变量),async 会把这个直接量通过 Promise.resolve() 封装成 Promise 对象。如果你返回了promise那就以你返回的promise为准 

复制代码
例1
async function async1 () {
  await async2();
  console.log('async1');
  return 'async1 success'
}
async function async2 () {
  return new Promise((resolve, reject) => {
    console.log('async2')
    reject('error')
  })
}
async1().then(res => console.log(res))

例2
async function async1 () {
  console.log('async2');
  throw new Error('error!!!')
  return 'async1 success'
}
async1().then(res => console.log(res))

//async2 报错信息

17.如果在async函数中抛出了错误,则执行终止
复制代码

综合

const p1 = new Promise((resolve) => {
  setTimeout(() => {
    resolve('resolve3');
    console.log('timer1')
  }, 0)
  resolve('resovle1');
  resolve('resolve2');
}).then(res => {
  console.log(res)
  setTimeout(() => {
    console.log(p1)
  }, 1000)
}).finally(res => {
  console.log('finally', res)
})

//  'resolve1'
    'finally' undefined
    'timer1'
    Promise{<resolved>: undefined}

18.考点:状态一经改变就不能再改 ,finally不管状态是resloved还是rejected都会执行,它的回调函数是接收不到promise结果的,所以为undefined;打印p1就是打印finally的返回值 finally接收不到promise的结果 它默认是上一个promise也就是then的返回值 但是then没有return所以就是undefined
复制代码

原文来自:juejin.cn/post/684490…

文章分类
前端
文章标签