JavaScript学习笔记之Promise(承诺)实战

本文介绍了Promise在JavaScript中的重要性,它如何解决回调地狱问题,详细阐述了Promise的状态转换、then方法、catch方法、Promise.resolve()、Promise.reject()、Promise.all()和Promise.race()的使用,并探讨了Promise的优缺点。通过示例,演示了如何创建和使用Promise,包括将setTimeout转化为Promise。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、为什么会出现promise?

在实际开发过程中,经常会遇到某些耗时的js操作。其中,包含异步操作也包含同步操作,但是他们都不是立马可以得到结果的。此时,一般会为其指定一个回调函数,即事先规定,一旦他们运行结束,应该会调用那些函数。

JS采用回调来处理异步编程,但是如果出现多层嵌套,也就是常说的"回调地狱"。"回调地狱"不但维护困难,也更容易滋生bug。因此promise出现。

Promise将原来回调地狱中的的回调函数,从横向变为纵向。

 //回调地狱
    asyncOperation(function (data) {
        // 处理data
        anotherAsync(function (data2) {
            // 处理data2
            yetAnotherAsync(function () {
                //完成
            });
        });
    });
    


    //Promise
    PromiseSomething()
        .then(function (data) {
            // 处理data
            return anotherAsync();
        })
        .then(function (data2) {
            // 处理data2
            return yetAnotherAsync();
        })
        .then(function () { 
            //完成
        })

 

二、Promise规范 

  1. 一个promise可能有三种状态:等待(pending)、已完成(fulfilled)、已拒绝(rejected)。
  2. 一个promise状态只可能从"等待"转到"完成"态或者"拒绝"态,不能逆向转换,同时"完成"和"拒绝"状态不能相互转换。
  3. promise必须实现then方法(可以说,then是promise的核心),而且then必须返回一个promise,同一个promise的then可以调用多次,并且回调的执行顺序跟他们被定义时的顺序一致。
  4. then方法接收两个参数,成功回调,失败回调。

三、Promise优缺点

优点

  1. 有了Promise对象避免了回调地狱
  2. Promise对象提供统一的接口

缺点

  1. 无法取消promise,一旦建立立即执行。
  2. 如果不设置回调函数,Promise内部抛出的错误,不会反映到外部。
  3. 当出于pending状态时,无法得知目前在哪一个阶段。

四、Promise 基本API

  1. Promise.resolve() :生成一个成功的promise对象
  2. Promise.reject():生成一个错误的promise对象
  3. Promise.prototype.then():核心部分(返回一个新的promise)
  4. Promise.prototype.catch():异常捕获
  5. ​​​​​​​Promise.all() 
  6. Promise.race()

​​​​​​​      Promise.all()

  • 接收promise对象组成的数组作为参数
  • 当这个数组里所有的promise对象全部变成resolve或遇到第一个reject状态的时候,才会去调用.then方法。
  • 传递给Promise.all的promise并不是一个个顺序执行的,而是同时开始,并行执行的。

​​​​​​​Promise.race()(最先执行的promise结果)

  • 只要有一个promise对象进入resolve或者reject状态的话,就会调用后面的.then方法
  • 如果一个promise对象执行完了,还会继续执行后面的对象,因为promise无法中断

​​​​​​​五、Promise基本用法

1、创建promise对象

  1. new Promise(fn)返回一个promise对象
  2. 在fn中指定异步等处理
  3. 在处理结果正常时,调用resolve
  4. 处理结果异常,调用reject
    function createPromise(URL) {
            return new Promise(function (resolve,reject) {
                var req = new XMLHttpRequest();
                req.open('GET',URL,true);
                req.onload = function () {
                    if(req.status === 200){
                        if(req.readyState ===4){
                            resolve(req.responseText);
                        }
                    }else {
                        reject(new Error(req.responseText));
                    }
                };
                req.onerror = function () {
                    reject(new Error(req.statusText));
                };
                req.send();
            })
        }
        
        // 示例
        var URL = "http://www.baidu.com";
        createPromise(URL)
            .then(function onFuilled(value) {
                console.log(value);
            })
            .catch(function onRejected(error) {
                console.log(error);
            })
        //.catch只是promise.then(undefined,onRejected)的别名

2、promise.prototype.then()

  • 它的作用是为Promise实例添加状态改变时的回调函数。前面说过,then方法的第一个参数是Resolved状态的回调函数,第二个参数(可选)是Rejected状态的回调函数。

  • then方法返回的是一个新的Promise实例。因此可以采用链式写法,即then方法后面再调用另一个then方法。

3、Promise.prototype.catch()

Promise.prototype.catch方法是.then(null,rejection)的别名,用于指定发生错误时的回调函数。

createPromise(URL).then(function (value) {  }).catch(function (error) { 
        console.log(error);
    });

4、Promise.resolve()

有时需要将现有对象转为Promise对象,Promise.resolve方法就起到这个作用。
该函数的参数四种情况:
(1)参数是一个Promise实例,那么Promise.resolve将不做任何操作,原封不动的将实例返回。
(2)参数是一个thenable对象,会将其转为Promise对象,然后立即执行该对象的then方法。
(3)参数不是具有then方法的对象,或根本就不是对象。比如说字符之类,则Promise.resolve方法返回一个新的Promise对象,并且状态Resolved。
(4)不带有任何参数,直接返回一个状态为Resolved的Promise对象。

  • 使用Promise.resolve()创建Promise对象
/*静态方法 Promise.resolve(value) 可以认为是 new Promise() 方法的快捷方式。*/
//比如 
Promise.resolve(1)
.then(function(value){
    console.log(value);
});  
//可以认为是以下代码的语法糖。
new Promise(function(resolve){ 
  resolve(1);
})
.then(function(value){
    console.log(value);
});
// 控制台输出1
注意: 无论Promise.resolve的参数是什么,只要变成了rejected,或者resolved。都会执行then里面的resolve函数

 

5、Promise.reject()

Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。

Promise.reject('这是错误的信息').then(function(){

},function(res){
     console.log(res); //这里是错误信息  
});
 注意: 无论Promise.reject的参数是什么,只要变成了rejected,或者resolved。都会执行then里面的reject函数。

 

6、Promise.all()

7、Promise.race()

六、将定时器setTimeout Promise化

function timer(fn,time) {
        return function () {
            return new Promise((resolve,reject)=>{
                setTimeout(function(){
                    fn();
                    resolve();
                },time);
            });
        }
    }
    
    Promise.resolve()
        .then(
            timer(function () {
                console.log('1')
            },1000)
        )
        .then(()=>{
            console.log('2');
    });

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值