同步和异步

一、为什么JavaScript是单线程?

原因:因为JS是一个脚本语言,它主要是面对于浏览器的用来于用户互动的以及DOM的操作。因此

才决定出它是单线程。如果是多线程,它就会带来复杂的同步问题。所以决定JS是单线程。

二、同步和异步的任务

1、因为js是单线程就会带来一些问题。就是所有任务都会排队,前一个任务完成,后一个任务才能执行

那如果前一个任务耗费时间长,那后面的任务岂不是要一直等待。 于是就出现了两种任务

同步任务:在主线程上排队的任务,只用前一个任务执行完毕,后一个任务才能紧接着执行。

异步任务:先不进入主线程,而是先进入到任务队列,只用任务队列通知主线程任务完成,才能进入到

主线程然后执行完毕。

三 事件和回调函数

1.任务队列就是一个事件的队列,当io设备完成一个任务 ,就在任务队列中添加一个事件,表示相关

的任务异步任务可以进入到主线程当中 。

2.所谓的回调函数就是那些被主线程观其来的代码。异步任务必须指定回调函数。当主线程开始执行

异步任务的时候,就调用对应的回调函数

注:任务队列先进先出

异步任务遇到的问题,以及解决的方案

一、

凡是异步任务,都要使用回调函数,而使用回调函数就会遇到问题那就是"回调地狱"。

而所谓的"回调地狱"就是回调函数中嵌套回调,使代码更加混乱,难懂,以及以后的修改

都会出现问题。

解决方案:

Promise

Promise 对象是 JavaScript 的异步操作解决方案,为异步操作提供统一接口。它起到代理作用(proxy),充当异步操作与回调函数之间的中介,使得异步操作具备同步操作的接口。Promise 可以让异步操作写起来,就像在写同步操作的流程,而不必一层层地嵌套回调函数。

例:

const p1 = new Promise((resolve , reject) =>{
     //resolve() 表示成功时执行的函数,结果传入其中
      //reject() 表示失败时执行的函数
     /*
     承诺
      promise 有三种状态:
      
      pedding 正在执行中
      resolve 执行成功
      reject  执行失败
     */
     //只要在promise中没用调用resolve或者reject去更改状态,那么promise一直处于peeding状态
 });
// then里面可以写两个回调函数,第一个回调函数时成功状态时的数据,第二个状态时失败时结束的数据
 p1.then(() =>{
 }, ()=>{})

Promise.prototype.catch( )

方法是.then(null,rejection)或.then(undefied,rejection)的别名,用于指定发生错误时的回调函数6

const promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});

Promise.prototype.finally( )

finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

Promise.prototype.all( )

Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.all([p1, p2, p3]);

上面代码中,Promise.all()方法接受一个数组作为参数,p1p2p3都是 Promise 实例,如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为 Promise 实例,再进一步处理。另外,Promise.all()方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。

p的状态由p1p2p3决定,分成两种情况。

(1)只有p1p2p3的状态都变成fulfilledp的状态才会变成fulfilled,此时p1p2p3的返回值组成一个数组,传递给p的回调函数。

(2)只要p1p2p3之中有一个被rejectedp的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。

Promise.prototype.race( )

Promise.race()方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。

const p = Promise.race([p1, p2, p3]);

上面代码中,只要p1p2p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。

Promise.race()方法的参数与Promise.all()方法一样,如果不是 Promise 实例,就会先调用下面讲到的Promise.resolve()方法,将参数转为 Promise 实例,再进一步处理。

下面是一个例子,如果指定时间内没有获得结果,就将 Promise 的状态变为reject,否则变为resolve

async await

语法糖

async function getSrc() {
      const al = await ajax('get' ,'./1.json');
      // console.log(al);
      const src1 = al.src;
      const all = await ajax('get' ,src1);
      // console.log(all);
      const src2 = all.src;
      const alll =await ajax ('get',src2);
      console.log(alll);
     }
​
   getSrc();

宏任务和微任务

一、

ES6规范中,microtask称为jobs,macrotask称为task

宏任务是由宿主发起的,而微任务由JavaScript自身发起

二、

二者的区别:

new Promise((resolve) => {  console.log('promise')  resolve() }) .then(() => {    console.log('then1') }) .then(() => {    console.log('then2') })​

//当 new Promise 执行时它是同步的

//注释:当代码执行时 先同步在异步 然后微任务 宏任务;

requestAnimationFrame()的使用详解

一、

说明:window.requestAnimationFrame()这个API是浏览器提供的js全局方法,针对动画效果。

异步,传入的函数在重绘之前调用。

注意:若你想在浏览器下次重绘之前继续更新下一帧动画,那么回调函数自身必须再次调用window.requestAnimationFrame()

语法:

window.requestAnimationFrame(callback)

requestAnimationFrame与setTimeout的区别:

与setTimeout相比,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值