likes
comments
collection
share

小小异步,看我Promise直接把你优雅拿下!

作者站长头像
站长
· 阅读数 26

前言

今天我们一起学习JavaScript的ES6版本中引入的处理异步操作的对象---Promise。在学习Promise之前呢,我先带大家了解一下什么是异步。


同步和异步

在编程中,同步异步是两种不同的模式,同步操作是顺序执行的,一个任务必须等待前一个任务完成后才能开始。例如,在同步调用函数时,调用方会被阻塞,直到被调用的函数返回结果;而异步操作则是非阻塞的,任务可以同时进行,不必等待前一个任务完成。比如异步网络请求,发出请求后程序可以继续执行其他操作,无需等待响应。

所以同步比较适合处理少量,简单的任务,异步能够充分利用系统资源,比较适合处理一些复杂或者耗时的任务

早期异步的处理

为了让大家更直观地了解到Promise的“优雅”之处,我们先来了解一下没有Promise之前,是怎么处理异步操作的。

  • 早期我们主要通过回调函数来处理异步操作:
var data = null
function a(cb) {
    setTimeout(function () {
        data = 'hello world'
        cb()
    }, 1000);
}

function b() {
    console.log(data);
}

a(b)//hello world

回调函数指的是将函数(本身)作为参数传递给另一个函数。当特定的事件发生或操作完成时,主函数会调用这个传递进来的回调函数来执行相应的操作。在这里,b就是回调函数,它被作为参数传递给了函数aa接收并调用了函数b,使得打印结果为hello world 而并不是null。这样就实现了异步操作。

单从这段代码来看,回调函数处理异步操作是不是还挺方便的呢?但是一旦代码量多了起来,嵌套了多层回调函数,实现和修改起来就会极其的麻烦,牵一发而动全身,这种情况我们通常称为“回调地狱”。


Promise

为了更优雅地执行异步操作,在Js的ES6版本中引入了Promise

Promise是一个用于处理异步操作的对象,它代表一个还没完成但最终会完成(或失败)并返回其结果值的异步操作。 它可以是以下三种状态之一:

  • pending(进行中):异步操作正在进行
  • resolve(已完成):异步操作已完成,并有一个结果值
  • reject(已失败):异步操作执行失败,并有一个错误

创建Promise对象

const pro = new Promise((resolve,reject) =>{
    //模拟异步操作
    setTimeOut(() =>{
       if(/* 异步操作成功 */){
           resolve("操作成功");
       }else{
           reject("数据获取失败");
       }
    },1000)
})

Promise对象通过构造函数创建,并接收一个执行器函数作为参数,该执行器函数会立即执行,并有两个参数:resolvereject,分别用来改变promise对象的状态。

.then() / .catch() / .finally() 方法

这些方法是promise对象自带的方法,其中, .then()方法用来处理成功的状态:即如果promise对象的状态被切换为resolve,就会执行.then()中的代码。.catch()用于捕获 Promise 链中的错误,通常用在.then()的后面,当状态被切换成reject或者.then()中的执行出现错误,都会执行.catch()中的代码。我们还可以使用.finally()方法来处理无论成功还是失败都会执行的代码

pro.then(value =>{
    console.log('状态:',value)  //状态:操作成功
})
.catch(error =>{
    console.log('捕获错误:',error)  //捕获错误:数据获取失败
})
.finally(() =>{
    console.log(无论成功或者失败,都会执行'')
})
  • 链式调用:Promise支持链式调用,这意味着我们可以在一个promise对象后面接多个.then().catch()
pro
.then(result => {
    console.log('第一个then成功:', result);
    return '我是第二个then';
})
.then(result2 => {
    console.log('第二个then成功:', result2);
})
.catch(error => {
    console.log('某个then或之前的catch失败:', error);
});

.all() / .race() 方法

  • .all()方法可以用来处理多个promise,调用时接收一个数组返回一个promise对象:数组里的每一项都得是promise对象,只有当这些promise都成功时,才能返回一个成功的promise只要有一个promise不成功,就会返回一个失败的promise
Promise.all([promise1, promise2])
.then(results => {
    console.log('所有的Promise都成功了:', results);
})
.catch(error => {
    console.error('至少有一个Promise失败了:', error);

* .race()方法同样是接收一个promise数组,但是他会立即返回第一个完成的promise的结果,无论他是成功还是失败。

const p1 = new Promise((resolve,reject) => {
    setTimeout(() =>{
        console.log("p1");
    },1000)
})

const p2 = new Promise((resolve,reject) =>{
    setTimeout(() => {
        console.log("p2")
    },2000)
})

Promise.race([p1,p2])
.then( result => {
    console.log("谁先运行成功:", result)
})
.catch( error => {
    console.error("谁先运行失败:", error)
})

在这个代码示例中:显然是p1先执行成功,所以打印的结果是谁先运行成功:p1 。因为在这个代码示例中p1p2都一定会成功运行,所以不会执行.catch() ,但是如果p1p2中有任何一个执行错误,都会打印先执行失败的promise对象的错误原因。


总结

Promise 提供了一种强大的方式来处理异步操作,使得代码更加清晰和易于管理。

  • 当promise对象的状态从pending切换成resolve时,就会执行.then()中的代码。当状态切换为reject时,就会被.catch()捕捉到错误,就会执行.catch()中的代码。且.then().catch()支持链式调用。

  • .all().race()方法是Promise身上的静态方法。.all()会接收一个promise数组作为参数,当数组中所有的promise对象都执行成功,则返回一个成功的Promise,否则就返回一个失败的Promise。

  • .race()同样接收一个promise数组,它会返回第一个执行完毕的promise的执行结果,无论是成功或失败。

转载自:https://juejin.cn/post/7389446501133762598
评论
请登录