[ArkTs]对Promise的理解

Promise是什么?

Promise 是用来管理异步操作的对象,可以获取成功(或失败)的结果,代表了一个尚未完成的异步操作,最终会以成功(fulfilled)或失败(rejected)的状态结束。

Promise 的设计目的是为了解决回调地狱(多层回调函数嵌套)的问题,使得异步流程更加清晰和易于管理。

下面是两种方式的对比

代码示例ArkTs语法:

// 回调地狱写法
const req = http.createHttp()
req.request('接口1')
  .then(res1=>{
    req.request('接口2?p=接口1的结果res1')
      .then(res2=>{
        req.request('接口3?p=接口2的结果res2')
          .then(res3=>{
            req.request('接口4?p=接口3的结果res3')
              .then(res4=>{
                req.request('接口5?p=接口4的结果res4')
                  .then(res5=>{
                    req.request('接口6?p=接口5的结果res5')
                      .then(res6=>{

                      })
                  })
              })
          })
      })
  })

// 使用Promise优化后的写法
// 链式编程回调地狱写法
const req = http.createHttp()
req.request('接口1')
  .then(res1 => {
    return req.request('接口2?p=接口1的结果res1')
  })
  .then(res2 => {
    return req.request('接口3?p=接口2的结果res2')
  })
  .then(res3 => {
    return req.request('接口4?p=接口3的结果res3')
  })
  .then(res4 => {
    return req.request('接口5?p=接口4的结果res4')
  })
 .then(res5 => {
    return req.request('接口6?p=接口5的结果res5')
  })
 .then(res6 => {
    
  })

关于Promise 的几个关键点:

1. 状态:

3432677161614c7aaedb63aa1cffeadf.png

Pending(待定):初始状态,既不是成功也不是失败。

Fulfilled(已兑现):异步操作成功完成。

Rejected(已拒绝):异步操作失败。

2. 方法:

then:用于注册回调函数。当 Promise 处于 fulfilled 状态时,第一个回调函数(通常称为 onFulfilled)会被调用;当 Promise 处于 rejected 状态时,第二个回调函数(通常称为 onRejected)会被调用。

catch:用于注册一个回调函数处理错误,这个回调函数会在 Promise 被 reject 时被调用。

finally:无论结果是 fulfilled 还是 rejected,都会被执行。(用的较少)

Promise 的静态方法

resolve 和 reject 这两个在封装的时候见得多一些,不需要实例化,直接就可以获取 成功 或者 拒绝 的 Promise 对象

Promise.resolve   

//返回一个成功原因的 Promise 对象

Promise.resolve('成功原因')
  .then(res => {
    AlertDialog.show({ message: res })
  })


Promise.reject   

//返回一个拒绝原因的 Promise 对象

Promise.reject('拒绝原因')
  .catch((err: string) => {
    AlertDialog.show({ message: err })
  })

Promise.race 

是什么:‌Promise.race()方法‌用于处理一组异步操作,并返回第一个完成的异步操作的结果

场景:多个服务器提供相同的数据,但响应时间不同,你想要最快的那个服务器给你响应数据


const p1 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('1')
  }, 2000)
})

const p2 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    reject('2')
  }, 1000)
})

// Promise.race方法作用:可以执行一组异步对象,返回第一个执行完成的异步对象的结果
Promise.race([p1, p2])
  .then(res => {
    console.log('race执行结果--->', res)
  })
  .catch((err:string)=>{
    console.log('err race执行结果--->', err)// 输出:err race执行结果---> 2(因为1000毫秒先执行完)
  })

/*race方法,可以执行一组异步对象
  注意点:最快的那个异步对象如果是成功状态,则使用.then来接受结果
  否则使用.catch来接收结果

  应用场景:多个服务器提供相同的数据,但响应时间不同,你想要最快的那个服务器给你响应数据

 */

Promise.all

是什么:‌‌Promise.all方法用于处理多个Promise实例,如果所有Promise实例都成功完成,将所有成功的结果作为一个数组返回,如果任何一个Promise实例失败,返回第一个失败的Promise实例的原因

场景:同时请求多个API

@Entry
@Component
struct Index {
  build() {
    Column() {
      Button('Promise.all基本语法')
        .onClick(() => {
          /*
           * 总结:
           * Promise.all的作用是?
           *   执行一组p对象,如果所有成功则返回所有的执行结果(数组类型)
           * .them() 接收成功的结果
           * 如果有一个执行失败,直接返回失败的数据 (.catch来接收)
           *
           * 缺点:只要有一个失败了,其他的都拿不到数据
           * 场景:多个请求要么同时拿到成功的数据,要么一个不要
           * */

          const p1 = new Promise<string>((resolve, reject) => {
            setTimeout(() => {
              resolve('1')
            }, 2000)
          })

          const p2 = new Promise<string>((resolve, reject) => {
            setTimeout(() => {
              reject('2')
            }, 1000)
          })

          const p3 = new Promise<string>((resolve, reject) => {
            setTimeout(() => {
              resolve('3')
            }, 1000)
          })

          Promise.all([p1, p2, p3])
            .then(res => {
              AlertDialog.show({ message: JSON.stringify(res, null, 2) })
            })
            .catch((err: string) => {
              AlertDialog.show({ message: '错误:' + err })
            })

        })
    }
    .height('100%')
    .width('100%')
  }
}

303314a3e685419c9b3d601d3079bb94.png

Promise.allSettled

相比于 all 方法,allSettled 可以获取所有的结果,无论成功失败

const p1 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('1')
  }, 2000)
})
const p2 = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    reject('2')
  }, 1000)
})
Promise.allSettled([p1, p2])
  .then((res) => {
    console.log('res:', JSON.stringify( res))
    //   [{"status":"fulfilled","value":"1"},{"status":"rejected","reason":"2"},{"status":"fulfilled","value":"itheima"}]
  }, (err: string) => {
    console.log('err:', err)
  })

3. 特点:

不可变性:一旦一个Promise 的状态被确定(fulfilled 或 rejected),就不能再改变。

调用 resolve 之后再调用 reject,状态还是 已兑现,反之亦然

链式调用:then 方法返回一个新的 Promise,可以链式调用,这样可以连续处理多个异步操作。

debe8921413e4473affb49f0f40c55b5.png

在 Promise的链式编程写法中,有如下2 个特性,需要了解:

  1. Promise 的 then 方法会自动返回一个新Promise 对象
  2. then 方法的返回值会影响这个 新Promise对象的结果是已兑现状态还是已拒绝状态

链式编程写出来的代码结构大概是这样子,then 和 then 以及 catch 之间是平级

let p = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('成功1')
  }, 10)
})

// 链式编程
/*
 * 特点:
 * 1. 后面的 .then是可以接受到前面.then返回的成功状态下的值
 * 2. 后面的.catch是可以接受前面.then中返回的失败状态下的值
 * 3. 一旦在某个.then里面返回的是一个失败状态的Pormise,则直接跳过其他
 * 的.then进入到.catch执行
 *
 * 总结:
 * 写法: p.then().then()....catch()
 * 注意点:如果 后一个.then需要用到前一个.then中的结果,需要在前一个
 * .then中 显示return一下
 * */
p
  .then(res1 => {
    console.log('res1--->', res1)
    // return '成功2'  // 等价于:return Promise.resolve('成功2')
    return Promise.reject('失败1')
  })
  .then(res2 => {
    console.log('res2--->', res2)
    return Promise.resolve('成功3')
    // return Promise.reject('失败1')
  })
  .then(res3=>{
    console.log('res3--->', res3)
  })
  .catch((err:string)=>{
    console.log('err--->',err )
  })

4. 用途:

异步操作的抽象:Promise 抽象了异步操作的过程,使得开发者可以以同步的方式编写异步代码。

错误处理:通过catch 方法可以集中处理异步操作中的错误。

组合异步操作:通过Promise.all 和 Promise.race 等方法可以方便地组合多个异步操作。

// 异步操作的抽象:Promise 抽象了异步操作的过程,使得开发者可以以同步的方式编写异步代码
const asyncOperation = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    resolve('异步操作完成');
  }, 1000);
});

asyncOperation
  .then((result) => {
    console.log(result); // 输出:异步操作完成 
  });

// 错误处理:通过catch 方法可以集中处理异步操作中的错误
const errorProneOperation = new Promise<string>((resolve, reject) => {
  setTimeout(() => {
    reject('发生错误');
  }, 1000);
});

errorProneOperation
  .then((result) => {
    console.log(result);
  })
  .catch((error:string) => {
    console.error(error); // 输出:发生错误
  });

// 组合异步操作:通过Promise.all 和 Promise.race 等方法可以方便地组合多个异步操作
const operation1 = new Promise<string>((resolve) => {
  setTimeout(() => {
    resolve('操作1完成');
  }, 1000);
});

const operation2 = new Promise<string>((resolve) => {
  setTimeout(() => {
    resolve('操作2完成');
  }, 2000);
});

// 使用Promise.all组合多个异步操作
Promise.all([operation1, operation2])
  .then((results) => {
    console.log(results.toString()); // 输出:['操作1完成', '操作2完成']
  });

// 使用Promise.race选择最快完成的异步操作
Promise.race([operation1, operation2])
  .then((result) => {
    console.log(result); // 输出:操作1完成
  });

补充:async函数和 await

(待补充)

总结

Promise 的引入极大地简化了异步编程模型,并且使得异步代码的编写更加优雅和易于理解。在现代 Web 开发中,Promise 已经成为处理异步操作的标准方式之一。

 

 

 

  • 23
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值