Promise 介绍

136 阅读1分钟

概述

Promise 是 JavaScript 中的一种对象,它用于处理异步操作。Promise 提供了一种标准化的方法来处理异步任务的结果,无论是成功(fulfilled)还是失败(rejected),并且允许以一种更有序、易于理解和维护的方式来组织代码,解决了回调函数嵌套过深的问题,即所谓的“回调地狱”。

为什么需要Promise

需求

  • 通过ajax发送请求获取id
  • 通过id获得name
  • 通过name获得email

代码

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <script src="../jquery-3.5.1.min.js"></script>
    <title>回调地狱</title>
</head>

<body>
    <script>
        $.ajax({
            type: 'GET',
            url: './data1.json',
            success: function (res) {
                let {
                    id
                } = res
                $.ajax({
                    type: 'GET',
                    url: './data2.json',
                    data: {id},
                    success: (res) => {
                        const {
                            userName
                        } = res
                        $.ajax({
                            type: 'GET',
                            url: './data3.json',
                            data: {id,userName},
                            success: (res)=>{
                                const {email} = res;
                                console.log(id,userName,email);
                            }
                        })
                    }
                })
            }
        });
    </script>
</body>
</html>

如上,需求中,email的获取需要先回去name属性,而name属性的获取又需要先获得id字段;同时还要保证方法执行的顺序,所以需要在相应的回调中调用下面的方法,这样就会造成回调地狱。

回调地狱是指在 JavaScript 中,由于异步操作的回调函数嵌套过深而导致代码难以阅读和维护的现象。

Promise基本语法

语法

new Promise((resolve,reject)=>{})
  • Promise接收一个函数为参数
  • 参数函数中有两个参数
  1. resolve:成功时调用
  2. reject:失败时调用
  • Promise 状态
  1. pending:准备,带解决,进行中
  2. fulfiled:已完成,成功
  3. rejected:失败,拒绝
  • 调用resolve函数,可以将状态改成fulfiled
const p = new Promise((resolve,reject)=>{
    resolve();
});
console.log(p);

结果

Promise {<fulfilled>: undefined}
[[Prototype]]: Promise
[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
  • 通过reject函数,可以将状态改成reject
const p = new Promise((resolve,reject)=>{
    reject();
});
console.log(p);

结果

Promise {<rejected>: undefined}
[[Prototype]]: Promise
[[PromiseState]]: "rejected"
[[PromiseResult]]: undefined

方法(then)

const p_resolve = new Promise((resolve, reject) => {
    resolve('成功结果')
});
p_resolve.then(()=>{
    // fulfilled
    console.log('成功时调用');
},()=>{
    // reject
    console.log('失败时调用');
});

const p_reject = new Promise((resolve, reject) => {
    reject('失败结果')
});
p_reject.then(()=>{
    // fulfilled
    console.log('成功时调用');
},()=>{
    // reject
    console.log('失败时调用');
});

结果

成功时调用
失败时调用

获取数据

通过立即执行函数实现的

const p_resolve = new Promise((resolve, reject) => {
    resolve('成功回调');
});
p_resolve.then((value)=>{
    console.log(value);
},(reason) => {
    console.log(reason);
});

const p_reject = new Promise((resolve, reject) => {
    reject('失败回调');
});
p_reject.then((value)=>{
    console.log(value);
},(reason) => {
    console.log(reason);
});

结果

成功回调
失败回调

方法返回值

仍然返回Promise实例,状态是pending,不是fulfilled

const p_resolve = new Promise((resolve,reject) => {
    resolve('成功回调');
});
const t_resolve = p_resolve.then((value) => {
    console.log(value);
},(value) => {
    console.log(value);
});
console.log(t_resolve);

const p_reject = new Promise((resolve,reject) => {
    reject('失败回调');
});
const t_reject = p_reject.then((value) => {
    console.log(value);
},(value) => {
    console.log(value);
});
console.log(t_reject);

结果

Promise {<pending>}[[Prototype]]: 
Promise[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
Promise {<pending>}[[Prototype]]: 
Promise[[PromiseState]]: "fulfilled"
[[PromiseResult]]: undefined
成功回调
失败回调

状态改变

状态不改变,不会执行then中的方法

new Promise((resolve, reject) => {

}).then((value) => {
    console.log('成功状态');
},(reason) => {
    console.log('失败状态');
});

使用return 可以将Promise实例更改状态。如果代码出错了,会返回reject 状态。

new Promise((resolve, reject) => {
    resolve(123);
}).then((value) => {
    console.log('成功状态1-1');
    // 如果这里的代码出错了,会返回reject 状态
    console.log(a);
},(reason) => {
    console.log('失败状态1-2');
}).then((value) => {
    console.log('成功状态2-1');
},(reason) => {
    console.log('失败状态2-2');
});

结果

成功状态1-1
失败状态2-2

catch方法

执行时机

  • Promise状态改为reject
  • Promise出错
new Promise((resolve,reject)=>{
    reject('失败状态');
}).catch((reason) => {
    console.log(reason);
})

new Promise((resolve,reject)=>{
    console.log(a);
}).catch((reason) => {
    console.log(reason);
})

结果

失败状态
ReferenceError: a is not defined
    at 8.catch方法.html:18
    at new Promise (<anonymous>)
    at 8.catch方法.html:17

解决回调地狱

new Promise((resolve, reject) => {
    $.ajax({
        type: 'GET',
        url: './data1.json',
        success: (res) => {
            resolve(res);
        },
        error: (reason) => {
            reject(res);
        }
    })
}).then((value) => {
    let {id} = value
    return new Promise((resolve, reject) => {
        $.ajax({
            type: 'GET',
            url: './data2.json',
            data: {id},
            success: (res) => {
                resolve(res);
            },
            error: (reason) => {
                reject(res);
            }
        })
    })
}).then((value) => {
    let {userName} = value
    return new Promise((resolve, reject) => {
        $.ajax({
            type: 'GET',
            url: './data3.json',
            data: {userName},
            success: (res) => {
                resolve(res);
            },
            error: (reason) => {
                reject(res);
            }
        })
    })
}).then((value) => {
    console.log(value);
}).catch((reason) => {
    console.log(reason);
})

优化

function getData(url,data={}){
    return new Promise((resolve,reject) => {
        $.ajax({
            type: 'GET',
            url: url,
            data,
            success: (res) => {
                resolve(res);
            },
            error: (reason) => {
                reject(res);
            }
        })
    })
}
new Promise((resolve, reject) => {
    getData('./data1.json');
}).then((value) => {
    let {id} = value
    return getData('./data2.json',{id});
}).then((value) => {
    let {userName} = value
    return getData('./data3.json',{userName});
}).then((value) => {
    console.log(value);
}).catch((reason) => {
    console.log(reason);
})

结语

通过 Promise,开发者能够编写出更加清晰、结构化的异步代码,使得复杂的异步逻辑易于管理和测试。随着 ES6 及后续版本对 Promise 的原生支持,Promise 已成为现代 JavaScript 开发中处理异步编程的核心工具之一。