【大白话】说JS的实际应用之异步操作(Promise,宏任务微任务)

87 阅读3分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第16天,点击查看活动详情

前言

大白话说JS内容包括:DOM的一些操作,Promise相关, 微任务宏任务,作用域,变量提升,闭包,变量类型,深浅拷贝,原型和作用域链,后续争取把js重点都记录上,深入浅出。


异步

啥是同步,啥是异步啊,这跟单线程,多线程有啥区别呀?嗯...

  1. 使用promise加载一张图片
  2. then,catch改变promise的状态
  3. async , await , 和Promise
  4. 微任务和宏任务

使用promise加载一张图片

考验对promise的基本使用情况。思路:实例化一个promise对象,对图片的加载分别成功与否用resolve, reject 处理。

function loadImage (src) {
  // 创建并实例化一个promise对象
  const promise = new Promise((resolve, reject) => {
    const img = document.createElement('img');
    // 如果图片加载成功,就传入图片进resolve
    img.onload = function () {
      resolve(img);
    }
    img.onerror = function () {
      const err = new Error(`图片加载失败, url:${{ src }}`)
      reject(err);
    }
    img.src = src;
  });
  return promise;
}

const url = 'https://cn.bing.com/th?id=OHR.WalhallaOverlook_ZH-CN1059655401_1920x1080.jpg&rf=LaDigue_1920x1080.jpg'
loadImage(url).then(img => {
  console.log('img', img);
}).catch(e => {
  console.log('err', e);
})

在这里插入图片描述

使用then,catch改变promise的状态

先说结论:

then 和 catch 正常返回的时候,Promise状态是 fulfilled ,抛出错误的时候,Promise 状态是 rejected。 fulfilled 状态的Promise执行then 的回调,而rejected则执行catch的回调。

怎么理解?看下面例子:

const p1 = Promise.resolve();

console.log('p1', p1);

const p1Then = p1.then(() => {
  console.log('p1Then', p1Then);
})

const p1Error = p1.then(() => {
  throw new Error('p1 then error')
})
console.log('p1Error', p1Error);

p1Then.then(() => {
  console.log('fulfilled状态走then回调');
}).catch(() => {
  console.log('fulfilled状态走catch回调');
})

p1Error.then(() => {
  console.log('p1Error走then回调');
}).catch(() => {
  console.log('p1Error走catch回调');
})

首先定义一个 resolve 返回值的promise对象,打印显示状态为 fulfilled ,保存当前信息在打印走catch还是then;然后在手动跑出个错误,打印当前状态,在判断走catch还是then。结果显示: 在这里插入图片描述 再回过头看先前的结论,发现也不难理解。reject类型的演示也差不多,结论见上。

async , await , 和Promise

这里也先说这三者的结论: 执行async 函数返回的都是Promise对象;promise.then的情况对应await ;promise.catch异常情况对应try...catch。

// async结论 :async返回的都是Promise对象
async function test1 () {
  return 1;
}
const result1 = test1();
console.log('result1', result1);

// await 结论:promise.then成功情况对应await
async function test2 () {
  const p2 = Promise.resolve(2);
  p2.then(data => {
    console.log('promise情况:', data);
  })
  const data = await p2;
  console.log('await情况:', data);
}
test2();

// promise.catch异常情况对应try...catch
async function test3 () {
  const p3 = Promise.reject(6);
  try {
    const data3 = await p3;
    console.log('data3', data3);
  } catch (e) {
    console.log('try-catch捕捉的promise异常:', e);
  }
}
test3();

在这里插入图片描述例子比较通俗易懂,配合结果应该能更清晰的理解结论。

微任务和宏任务

JS的一个执行代码机制,采用单线程的事件循环方式管理异步任务,优点简化编程模型,缺点无法发挥CPU的全部性能(但对前端其实没影响)

执行顺序:

  1. 先执行同步任务
  2. 微任务:process.nextTick,Promise,Async/Await
  3. 宏任务:计时器,ajax,读取文件,setTimeout,setInterval

事件循环大致按上述执行顺序执行。值得注意的是,Async/Await就是promise的一种语法糖,有Async没有Await,相当于同步任务,有了Await相当于是promise的then。

console.log('a');
setTimeout(()=>console.log('宏1'), 0);
(async ()=>{
  console.log(1);
  await console.log(2);//此处相当于.then()处理,将后面的打印放到微任务中,
  console.log(3);
  setTimeout(()=>console.log('宏2'), 0);
})().then(()=>{
  console.log(4);
});
console.log('b');
//a,1,2,5,3,4,宏1,宏2