Promise基础

本章将详细介绍Promise的基本语法、状态转换和创建方法,帮助您掌握Promise的核心概念和基本使用方式。

2.1 Promise构造函数

Promise构造函数用于创建Promise对象,它接受一个执行器函数(executor)作为参数。执行器函数在Promise创建时立即执行,它接受两个参数:resolve和reject函数。

示例:Promise构造函数

// Promise构造函数的基本语法
const myPromise = new Promise((resolve, reject) => {
    // 执行器函数
    // 异步操作逻辑
    if (/* 操作成功 */) {
        resolve(value);  // 将Promise状态设置为fulfilled
    } else {
        reject(error);   // 将Promise状态设置为rejected
    }
});

执行器函数的特点

  • 立即执行:执行器函数在Promise创建时立即同步执行
  • 两个参数:resolve和reject都是函数,由JavaScript引擎提供
  • 只能调用一次:resolve和reject函数只能被调用一次,多次调用无效

2.2 Promise的状态

Promise对象有三种状态,状态之间只能单向转换:

  • Pending(进行中):初始状态,既不是成功也不是失败
  • Fulfilled(已成功):操作成功完成,通过调用resolve函数转换
  • Rejected(已失败):操作失败,通过调用reject函数转换

示例:Promise状态转换

// Pending状态
const promise1 = new Promise(() => {});
console.log(promise1); // Promise {  }

// Fulfilled状态
const promise2 = new Promise(resolve => {
    resolve('成功');
});
console.log(promise2); // Promise { '成功' }

// Rejected状态
const promise3 = new Promise((resolve, reject) => {
    reject(new Error('失败'));
});
console.log(promise3); // Promise {  Error: 失败 }

2.3 resolve和reject函数

resolve和reject函数用于改变Promise的状态:

resolve函数

  • 将Promise状态从Pending转换为Fulfilled
  • 接受一个参数作为Promise的成功值
  • 如果参数是Promise对象,则原Promise的状态由参数Promise决定

reject函数

  • 将Promise状态从Pending转换为Rejected
  • 接受一个参数作为Promise的失败原因
  • 建议使用Error对象作为参数

示例:resolve和reject的使用

// resolve的使用
const promise1 = new Promise(resolve => {
    setTimeout(() => {
        resolve('数据获取成功');
    }, 1000);
});

promise1.then(result => {
    console.log(result); // 输出: 数据获取成功
});

// reject的使用
const promise2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(new Error('网络错误'));
    }, 1000);
});

promise2.catch(error => {
    console.error(error.message); // 输出: 网络错误
});

2.4 then方法

then方法用于指定Promise状态改变时的回调函数,它接受两个参数:

  • onFulfilled:Promise状态变为Fulfilled时调用的回调函数
  • onRejected:Promise状态变为Rejected时调用的回调函数(可选)

示例:then方法的使用

// 基本使用
const promise = new Promise(resolve => {
    resolve('成功');
});

promise.then(
    result => {
        console.log('成功:', result);
    },
    error => {
        console.log('失败:', error);
    }
);

// 只处理成功情况
promise.then(result => {
    console.log('成功:', result);
});

// 链式调用
promise
    .then(result => {
        console.log('第一步:', result);
        return '第二步结果';
    })
    .then(result => {
        console.log('第二步:', result);
    });

2.5 catch方法

catch方法用于指定Promise状态变为Rejected时的回调函数,是.then(null, onRejected)的别名。

示例:catch方法的使用

// 基本使用
const promise = new Promise((resolve, reject) => {
    reject(new Error('操作失败'));
});

promise.catch(error => {
    console.error('捕获到错误:', error.message);
});

// 链式调用中的错误处理
promise
    .then(result => {
        console.log(result);
        return '下一步';
    })
    .catch(error => {
        console.error('处理链中的错误:', error.message);
    });

2.6 finally方法

finally方法用于指定Promise状态改变后的回调函数,无论Promise是成功还是失败都会执行。finally方法在ES2018中被引入。

示例:finally方法的使用

// 基本使用
const promise = new Promise(resolve => {
    setTimeout(() => {
        resolve('操作完成');
    }, 1000);
});

promise
    .then(result => {
        console.log(result);
    })
    .catch(error => {
        console.error(error);
    })
    .finally(() => {
        console.log('清理工作');
    });

2.7 Promise的静态方法

Promise还提供了一些静态方法用于创建特定状态的Promise对象:

Promise.resolve()

返回一个以给定值解析的Promise对象。

示例:Promise.resolve()

// 直接返回一个成功的Promise
const promise1 = Promise.resolve('成功');

// 等价于
const promise2 = new Promise(resolve => resolve('成功'));

promise1.then(result => {
    console.log(result); // 输出: 成功
});

Promise.reject()

返回一个带有拒绝原因的Promise对象。

示例:Promise.reject()

// 直接返回一个失败的Promise
const promise1 = Promise.reject(new Error('失败'));

// 等价于
const promise2 = new Promise((resolve, reject) => reject(new Error('失败')));

promise1.catch(error => {
    console.error(error.message); // 输出: 失败
});

2.8 Promise的执行顺序

Promise的执行顺序遵循事件循环机制,理解执行顺序对于正确使用Promise非常重要。

示例:Promise执行顺序

console.log('1');

setTimeout(() => {
    console.log('2');
}, 0);

const promise = new Promise(resolve => {
    console.log('3');
    resolve();
});

promise.then(() => {
    console.log('4');
});

console.log('5');

// 输出顺序: 1, 3, 5, 4, 2

提示:Promise的then/catch/finally回调函数会被添加到微任务队列,优先级高于宏任务(如setTimeout)。

2.9 实践练习

通过实际练习加深对Promise基础概念的理解:

练习:创建一个模拟异步操作的Promise

// 创建一个模拟网络请求的Promise
function fetchData(url) {
    return new Promise((resolve, reject) => {
        // 模拟网络延迟
        setTimeout(() => {
            if (url === 'valid-url') {
                resolve({ data: '请求成功', status: 200 });
            } else {
                reject(new Error('请求失败'));
            }
        }, 2000);
    });
}

// 使用Promise
fetchData('valid-url')
    .then(response => {
        console.log('成功:', response);
    })
    .catch(error => {
        console.error('错误:', error.message);
    })
    .finally(() => {
        console.log('请求完成');
    });