JS中的promise以及 event loop 事件循环机制

Promise

1.如何使用 promise

虽然认识 promise 很久了,但是一直很排斥这个东西,突然来了兴趣,想要仔细研究一下。

MDN文档 可以看这里 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Using_promises

promise是一个实现异步编程的方式,它就是一个对象,代表异步操作的最终状态,作为一个函数返回的对象,我们可以在它上面绑定回调函数,而不需要在开始时将回调函数作为参数传入,避免多重回调函数造成的回调地狱。

const promise = initalize(fir);
promise.then(function1, function2);

这样,就将function1 和 function2 绑定作为initalize函数的回调,称为异步调用。

2.Promise对象的特点

  • 对象的状态不受外界影响:

一个promise对象代表一个异步操作, pending进行中, resolve|fulfilled完成, rejected失败,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作无法改变状态。

还有 finally()中的函数总会被执行。

  • 一旦状态改变,不会在变,任何时候都可以得到这个结果

promise对象的状态改变只有2中可能,pending变为resolve, pending变为rejected

只要发生上面2中变化,状态就会凝固保持,就算发生改变,再对promise对象添加回调函数也会立即得到这个结果。

 

 

 

3.异步调用的优点

1.链式调用:连续执行几个异步操作,上一个操作执行success后,带着执行结果去执行下一个操作。

doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);

简写为:

doSomething()
.then(result => doSomethingElse(result))
.then(newResult => doThirdThing(newResult))
.then(finalResult => {
  console.log(`Got the final result: ${finalResult}`);
})
.catch(failureCallback);

2.错误传递: 只需在尾部调用一次

doSomething()
.then(result => doSomethingElse(value))
.then(newResult => doThirdThing(newResult))
.then(finalResult => console.log(`Got the final result: ${finalResult}`))
.catch(failureCallback);

3.时序: 即时一个已经为resolve状态的Promise,传递给then()的函数也会被异步调用。

Promise.resolve().then(() => console.log(2));
console.log(1); // 1, 2

注意:传递到 then() 中的函数被置入了一个微任务队列,而不是立即执行,这意味着它是在 JavaScript 事件队列的所有运行时结束了,事件队列被清空之后,才开始执行:

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait().then(() => console.log(4));
Promise.resolve().then(() => console.log(2)).then(() => console.log(3));
console.log(1); // 1, 2, 3, 4

4.小试牛刀

1.函数执行顺序 宏任务与微任务

console.log('script start');

setTimeout(() => {
    console.log("timer1 over");
}, 0);

Promise.resolve().then(() => {
    console.log('promise1');
}).then(() => {
    console.log('promise2');
});

console.log('script end');

2.经典题 https://blog.csdn.net/MFWSCQ/article/details/105109727

async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}

async function async2() {
    console.log('async2');
}

console.log('script start');

setTimeout(()=>{
    console.log('setTimeout');
},0)

async1();

new Promise((resolve)=>{
    console.log('promise1');
    resolve();
}).then(()=>{
    console.log('promise2');
});

console.log('script end');

解析: 微任务的执行优先于宏任务;promise只要被定义就会立即执行;resolve和reject是异步执行的回调;await执行完,会让出线程。

宏任务: setTimeout setInterval script的全部代码

微任务:promise process.nextTick为node独有 Objcet.observe废弃

挂起任务时,js引擎会将所有任务分到宏任务和微任务队列,首先从宏任务队列取出一个任务,执行完毕后执行微任务队列中的所有任务顺序执行;然后,再从宏任务中取出第二个任务,重复上述过程,直至两个队列中的任务被取完。

流程:

1.执行 同步任务 console.log('script start');

2.遇到 setTimeout 把 console.log('setTimeout') 放到 macrotask 宏任务队列中,未执行;

3.执行async1 输出 async1 start,继而执行async2,把 console.log('async1 end');放入 microtask微任务队列中;

4.执行 new promise, 被定义就立即执行,输出 promise1,将console.log('promise2');放入 microtask微任务队列中;

5.执行同步任务 script end;

6.这样所有的macrotask任务执行完,开始执行micro微任务队列中的,顺序输出 async2 和 promise2

7.此轮中的宏任务执行完毕,开始执行宏任务队列中的下一个任务 也就是 setTimeout,输出 setTimeout

结果:

script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值