promise和async/await

96 阅读5分钟

1.回调函数

这一章教你如何做一个时间管理大师
我们试想一个排队办手续的场景,在轮到你之前,你可以玩手机,可以和朋友聊天,等等。可以做很多很多事情。这样就可以成功的打发这段排队等候的无聊时光,同时做好自己的事情,同时也不影响排队的进程。这样的过程和异步处理 的原理有点相似。

般来说,异步处理常常用于处理那些需要较长时间才能完成的操作,例如从服务器上获取数据、读取文件、进行网络请求等。如果使用同步处理,程序就会一直等待这些操作的完成,造成程序的阻塞。而使用异步处理,则可以充分利用程序的资源,同时处理其他任务

于是我们便引入了回调函数

setTimeout(function(){   
	console.log('执行了回调函数');
},3000)  //3000毫秒

我们让程序等个3000毫秒,之后自动执行
很好,3000毫秒以后执行就很合适。

但是在项目中不可能只有一个进程需要处理

        setTimeout(function () {  //第一层
            console.log('清早起来');
            setTimeout(function () {  //第二程
                console.log('真tm的困啊');
                setTimeout(function () {   //第三层
                    console.log('腰酸腿疼脖子硬');
                  							.......//好多好多层
                }, 1000)
            }, 2000)
        }, 3000)

这玩意就被称为**回调地狱,**推断个语法累死你

2.Promise

1.then.catch.finally的用法

在ES6中,引入了Promise这个概念,你可以把它类比为一个if-else语句
执行成功了怎么样,失败了怎么样

下面开始正文:
Promise原本的状态是_pending(初始状态)
当执行成功完成之后,状态从pending变成了
fulfilled(已对现),之后我们实行那些操作。
当执行操作失败之后,状态从pending变成了reject
(已拒绝)_,之后我们实行那些操作。
我们写一个案例
先翻译下,resolve是解决的意思,reject是拒绝的意思。

var myPromise = new Promise((resolve, reject) => {
  // 执行异步操作
  if (/* 异步操作成功 */) {
    resolve(value); // pending -> fulfilled
  } else {
    reject(error); // pending -> rejected
  }
});

myPromise
  .then(value => {
    // 成功处理异步操作的结果
  })
  .catch(error => {
    // 处理异步操作失败的情况
  })
  .finally(() => {
    console.log('执行完毕');
  });

也就是说,异步操作最终肯定只有两个结果,要么成功要么失败,这个叫Promise的东西,会带着**成功(resolve)或者失败(reject)**的信息一起返回

  • 如果带回来的是成功的信息,那就会执行后面程序中then()里面的代码。
  • 如果带回来的是失败的信息,那就会执行后面程序中catch()里面的代码。
  • 不论是成功还是失败,都会输出finally里面的东西。

当然了,上面的catch也不是必须的,你也可以这么写

var p = new Promise((resolve,reject)=>{
 //主动调用reject,并传入实参2
   reject(2)
})
// 此时,P的状态是rejected,且值promiseValue 是2.
p.then((res)=>{
   // p的状态是resolved
   // 所以这句代码不会执行。
   console.log("then,ok",res)
},(err)=>{
 // p的状态是rejected
 // 执行then的第二个参数
 // 并把promisevalue传进来。
    console.log("then,err",err)
})

2.链式处理

then返回的也是一个_fulfilled/reject值得,就是是否对现_

// 方法
function todo1() {
        console.log("一");
    }


    function todo2() {
        console.log("二");
      	console.log(a); //这里的a没有定义,会报错
    }


    function todo3() {
        console.log("三");
    }


    function todo4() {
        console.log("四");
    }


// 执行操作
    var p = new Promise((resolve, reject) => {
        resolve()
    })
// 分别调用方法
    p.then(todo1)
        .then(todo2)
        .then(todo3)
        .catch(todo4);

输出结果:一,二,四

流程:
p里面写的是resolve,那直接执行第一个then里面的代码。成功后返回resolve,可以进入第二个then(todo2)。
进入todo2中,console.log("二");先执行,但是由于a没有定义(通常情况下要写一个**var a;再写console.log(a);**但是这里没有写)执行失败,返回reject,这样就没法继续执行then,因为then必须要操作成功返回resolve才能进入,既然语句操作失败,那只能进入catch中,执行todo4,todo3不执行,直接输出4。

想要详细了解的朋友,点击这里:Promise

3.async/await

在刚刚提到的链式中,我们发现上面写的简单,但是理解起来超级麻烦,于是我们引入了async/await
这个是方便处理链式的一个语法糖
(语法糖就是原来使用一大串代码才能使用的东西,现在只需要把语法糖丢进去就可以使用,减少代码量)
他的基本写法是这样的

//这一段方法不用看
function fn() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

//看这里!!!
//1.async就是异步函数的一个标志
//2.await就是等待fn()这个函数执行完,执行完成后会返回一个promise值,也就是执行成功resolve或者失败reject
async function asyncCall() {
  console.log('calling');
  const result = await fn();
  console.log(result);
  // Expected output: "resolved"
}

1.async就是异步函数的一个标志
2.await就是等待fn()这个函数执行完,执行完成后会返回一个promise值,这个值的内容就是执行成功:resolve或者失败:reject。

好像也看不出来好在哪里,但是要是实行链式,那就牛了
举个例子

// 使用 async/await 处理异步操作
async function getDataWithAsync() {
  try {
    // 使用 await 关键字等待 fetch 方法返回的 Response 对象
    // 说人话就是看看这个链接请求成功了没
    const response = await fetch('https://api.example.com/data');
    // 使用 await 关键字等待 Response 对象的 json 方法返回的 Promise 对象
    // 说人话就是看看response转化成.json了没
    const data = await response.json();
    // 如果上面的都成功了(await返回resolve),输出这一句
    console.log(data);
  } catch (error) {
    // 如果上面的await返回的是reject,失败了,就输出这一句
    console.error(error);
  }
}


// 使用 Promise 处理异步操作
function getDataWithPromise() {
  // 使用 fetch 方法发送 HTTP 请求并返回 Promise 对象
  fetch('https://api.example.com/data')
    // 使用 then 方法注册回调函数处理 Response 对象
    .then(response => response.json())
    // 使用 then 方法注册回调函数处理 JSON 数据
    .then(data => console.log(data))
    // 使用 catch 方法捕获错误并输出错误信息
    .catch(error => console.error(error));
}

注意,第二段代码里面没有写promise,但是fetch返回的值是promise类型,也就是成功或失败,想要详细了解可以看这里:fetch()