Promise的介绍与使用——学习笔记

Promise

Promise是JS中进行异步编程的新解决方案(以前使用回调函数来解决异步编程)

从语法上来说:Promise是一个构造函数

从功能上来说:Promise对象用来封装一个异步操作并且可以获取起成功或失败的结果值

一、Promise状态改变

Promise共有三种状态pendingresolved(fulfilled)、rejected

状态的改变只有两种可能:

  1. pending——>resolved

  2. pending——>rejected

如果Promise的状态已经发生了改变,就不会在改变了。

二、Promise基本使用

通过resolved设置状态为成功,通过rejected设置状态为失败

通过then方法对成功和失败的状态进行处理

例子1:点击按钮,1s后显示是否中奖(30%的中奖概率)

<body>
    <div>
        <h2>Promise 初体验</h2>
        <hr />
        <button id="btn">点击抽奖</button>
    </div>
    <script>
        //生成随机数
        function rand(m,n){
            return Math.ceil(Math.random() * (n-m+1)) + m-1;
        }
        // 获取元素
        const btn = document.querySelector('#btn')
        // 绑定事件
        btn.addEventListener('click', function() {
            const p = new Promise((resolve, reject) => {
                setTimeout(() => {
                    // 获取从1-100的一个随机数
                    let n = rand(1,100)
                    // 判断
                    if (n <= 30) {
                        resolve(n) // 将 promise 对象的状态设置为【成功】
                    } else {
                        reject(n) // 将 promise 对象的状态设置为【失败】
                    }
                }, 1000);
            })
            // console.log(p)
            // 调用then方法
            p.then((value) => {
                alert(`success:${value}`)
            }, (reason) => {
                alert(`fail:${reason}`)
            })
        })
    </script>
</body>

例子2:使用Promise封装一个ajax的get请求

function sendAJAX(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest()
        xhr.responseType = 'json'
        xhr.open('GET', url)
        xhr.send()
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4) {
                if(xhr.status >= 200 && xhr.status < 300) {
                    resolve(xhr.response)
                } else {
                    reject(xhr.status)
                }
            }
        }
    })
}
sendAJAX('https://api.apiopen.top/getJoke').then(res => {
    console.log(res)
}, reason => {
    console.log(reason)
})

三、Promise中的API

3.1、Promise构造函数

  1. executor函数:执行器(resolve,reject) => {}

  2. resolve函数:内部定义成功时调用该函数

  3. reject函数:内部定义失败时调用该函数

3.2、then&catch

3.2.1、Promise.prototype.then方法

(onResolved, onRejected) => {}

  1. onResolved函数: 成功的回调函数

  2. onRejected函数:失败的回调函数

3.2.2、Promise.prototype.catch方法

(onRejected) => {}

  1. onRejected函数:失败的回调函数,相当于then()方法的语法糖
let p = new Promise((resolve, reject) => {
    console.log('11')
    reject('error')
})
console.log('22')

// p.then(value => {}, reason => {})

p.catch(reason => {
    console.log(reason)
})

注意:在Promise中的代码是同步调用的,所以上面的代码会先输出11再输出22

3.3、Promise.resolve方法

(value) => {} 快速返回一个Promise对象

  1. value成功的数据或Promise对象
  • 传入的参数为非Promise类型的对象,则返回结果为成功

  • 传入的参数为Promise对象,则参数结果决定了resolve的结果

let p1 = Promise.resolve(1)
let p2 = Promise.resolve(new Promise((resolve, reject) => {
    reject('error')
}))
console.log(p2)

p2.catch(reason => {
    console.log(reason)
})

3.4、Promise.reject方法

(resone) => {}

  1. resone:失败的原因,方法会返回一个失败的对象,不论里面的数据是成功还是失败
let p = Promise.reject('3')
let p1 = Promise.reject(new Promise((resolve, reject) => {
    resolve(3223)
}))
console.log(p)
console.log(p1)

3.5、Promise.all方法

(promises) => {}

返回一个新的Promise,只有所有Promise都成功才成功,只要有一个失败了就直接失败

  1. promsies:包含nPromsie的数组
let p1 = new Promise((resolve, reject) => {
    resolve('ok')
})
let p2 = Promise.resolve('success')
let p3 = Promise.reject('fail')
const result = Promise.all([p1, p2, p3])
console.log(result)

3.6、Promise.race方法

(promises) => {}

返回一个新的Promise,第一个完成的Promise的结果状态就是最终的结果状态

  1. promises:包含nPromsie的数组
let p1 = new Promise((resolve, reject) => {
    // setTimeout(() => {
        resolve('OK');
    // }, 1000);
})
let p2 = Promise.resolve('Success');
let p3 = Promise.resolve('Oh Yeah');

//调用
const result = Promise.race([p1, p2, p3]);

console.log(result);

四、Promise的关键问题

4.1、Promise的状态如何改变

  1. resolve(value):如果当前是pending就会变为resolved

  2. reject(reason):如果当前是pending就会变为rejected

  3. 抛出异常:如果当前是pending就会变为rejected

4.2、Promise指定多个成功或失败回调函数,都会调用吗

Promise改变为对应状态时都会调用

let p = new Promise((resolve, reject) => {
    resolve('OK');
});

///指定回调 - 1
p.then(value => {
    console.log(value);
});

//指定回调 - 2
p.then(value => {
    alert(value);
});

4.3、改变Promise状态和指定回调函数谁先谁后

正常情况是先制定回调再改变状态,也可以先改变状态再指定回调

在执行器中直接调用resolve()/reject()或者延迟更长的时间在调用then()方法都可以使先改变状态再指定回调

如果先指定回调,当状态发生改变时,回调函数就会调用,得到数据

如果先改变状态,那当指定回调时,回调函数就会调用,得到数据

let p = new Promise((resolve, reject) => {
    // setTimeout(() => {
        resolve('OK');
    // }, 1000);
});

p.then(value => {
    console.log(value);
},reason=>{

})

4.4、Promise.prototype.then()返回的新Promise结果状态由什么决定

  • then()指定的回调函数执行结果决定。

    • 如果抛出异常,新的Promise变为rejectedreason为抛出的异常

    • 如果返回的是非Promise的任意值,新Promise变为resolved

    • 如果返回的是另一个新Promise,此Promise的结果就会成为新Promise的结果

    • 如果没有返回值,则会返回一个成功状态的Promise值为undefined

let p = new Promise((resolve, reject) => {
    // setTimeout(() => {
        resolve('ok')
    // }, 1000);
})

let result = p.then(value => {
    console.log(value)
    // 出错
    // throw 'error'
    // 不是promise
    // return 521
    // promise 对象
    // return new Promise((resolve, reject) => {
    //     // resolve('success')
    //     reject('fail')
    // })
}, reason => {
    console.warn(reason);
})

console.log(result)

4.5、Promise如何串连多个操作任务

Promisethen()返回一个新的Promise,可以看成then()的链式调用。通过then的链式调用串联多个同步或异步任务

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('ok')
    }, 1000);
})
p.then(value => {
    return new Promise((resolve, reject) => {
        resolve('success')
    })
}).then(value => {
    console.log(value)
}).then(value => {
    console.log(value)
}) 

4.6、Promise异常穿透

当使用Promisethen链式调用时,可以在最后指定失败的回调,前面的操作出了任何异常,都会传到最后失败的回调中处理

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
        // reject('Err');
    }, 1000);
});

p.then(value => {
    console.log(111);
}).then(value => {
    throw '失败啦!';
    // console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});

4.7、中断Promise链

当使用Promisethen链式调用时,在中间中断后就不能再调用后面的回调,如果还想在后面调用回调函数,可以在回调函数中返回一个pendding状态的Promise对象

let p = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('OK');
    }, 1000);
});

p.then(
    // value => {
        // console.log(111);
        // 有且只有一个方式
        // return new Promise(() => {});
    // }
).then(value => {
    console.log(222);
}).then(value => {
    console.log(333);
}).catch(reason => {
    console.warn(reason);
});
posted @ 2022-04-07 08:34  z1n4q2  阅读(68)  评论(0编辑  收藏  举报