Promise:JavaScript 异步编程的基石

TypeScript 简易教程
一、TypeScript前导
二、TypeScript基础语法
三、TypeScript变量
四、TypeScript Number+String类型
五、TypeScript运算符
六、TypeScript语句
七、TypeScript函数
八、TypeScript 容器类型
九、TypeScript 接口、类、对象
十、TypeScript 命名空间、模块、声明文件
十一、Promise:JavaScript 异步编程的基石
十二、TypeScript:Async Functions

Promise是JavaScript中用于处理异步操作的一种编程模式,自ECMAScript 6(ES6)起成为语言标准的一部分。它提供了一种更为优雅和可控的方式来处理异步操作,相较于传统的回调函数,Promise能够更好地解决“回调地狱”问题,增强代码的可读性和可维护性。本文将详细介绍Promise的概念、基本用法、链式调用、静态方法以及在实际开发中的应用案例。

一、Promise的基本概念

Promise代表一个异步操作的最终完成(或失败)及其结果的容器。它有三种状态:

  1. Pending(等待中):初始状态,既不是fulfilled也不是rejected。
  2. Fulfilled(已成功):表示操作成功完成,此时Promise的值为resolve传递的值。
  3. Rejected(已失败):表示操作失败,此时Promise的值为reject传递的原因。

一旦Promise从Pending变为Fulfilled或Rejected,它的状态就不可更改了,这称为Promise的不可逆性。

二、Promise的创建与使用

Promise构造函数接受一个函数作为参数,该函数接收两个参数:resolvereject,分别用于改变Promise的状态。

const myPromise = new Promise((resolve, reject) => {
    setTimeout(() => {
        const success = true;
        if (success) {
            resolve("操作成功");
        } else {
            reject("操作失败");
        }
    }, 2000);
});

resolve和reject 作为参数传递给Promise构造函数中的执行器(executor)函数。

  • resolve: 此函数用于将Promise的状态从pending(等待中)变为fulfilled(已成功)。当异步操作成功完成,或者你希望以某种成功的结果来解决Promise时,你应该调用resolve函数。resolve可以接受一个参数,这个参数将作为Promise的返回值传递给之后通过.then方法注册的回调函数。这个参数可以是任何类型的值,包括普通数据、对象,甚至是另一个Promise。
  • reject: 此函数用于将Promise的状态从pending变为rejected(已失败)。当你希望以一个错误原因来拒绝Promise,表示异步操作未能成功完成时,应调用reject函数。同样地,reject也接受一个参数,该参数作为错误原因传递给之后通过.catch方法注册的错误处理回调函数。这个参数通常是一个错误对象,用于描述失败的具体原因。

三、Promise的消费

then方法

.then()方法用于指定在Promise变为fulfilled状态时的回调函数,可以链式调用来处理多个后续操作。

myPromise.then(
    value => console.log(value), // 当Promise成功时的处理
    reason => console.error(reason) // 当Promise失败时的处理
);

catch方法

.catch()方法用于指定在Promise变为rejected状态时的回调函数,可以捕获前面链式调用中所有未被捕获的错误。

myPromise.catch(error => console.error(error));

四、Promise的链式调用

通过.then().catch()可以实现Promise的链式调用,这样可以按顺序执行一系列异步操作,每个操作都依赖于前一个操作的成功或失败。

myPromise
    .then(result => {
        console.log(result);
        return "下一个操作";
    })
    .then(nextResult => console.log(nextResult))
    .catch(error => console.error(error));

五、Promise的静态方法

Promise提供了几个静态方法,用于处理多个Promise的情况:

  • Promise.all():等待所有的Promise都变为fulfilled状态,然后返回一个新的Promise,其结果是一个包含所有fulfilled状态的Promise结果的数组。如果有任何一个Promise变为rejected状态,则立即返回并拒绝,不等待其余的Promise。
// 假设有三个异步操作,分别返回 Promise
function fetchUser(userId) {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log(`Fetching user ${userId}...`);
            // 模拟异步操作成功
            resolve({ id: userId, name: `User ${userId}` });
            // 如果想要模拟失败,可以使用 reject(new Error('Fetch failed'))
        }, 1000 * userId);
    });
}

// 使用 Promise.all 同时发起三个异步请求
const userIds = [1, 2, 3];
const userPromises = userIds.map(userId => fetchUser(userId));

Promise.all(userPromises)
    .then(users => {
        console.log("所有用户数据已获取:", users);
    })
    .catch(error => {
        console.error("其中一个请求失败:", error);
    });
  • Promise.race():只要任意一个Promise变为fulfilled或rejected状态,就立即返回并结束,不等待其他Promise。
function timeout(ms) {
    return new Promise((resolve, reject) => {
        setTimeout(reject, ms, 'Timeout!');
    });
}

function requestWithTimeout(url, timeoutMs) {
    const requestPromise = fetch(url);
    const timeoutPromise = timeout(timeoutMs);
    
    return Promise.race([requestPromise, timeoutPromise])
        .then(response => {
            if (response === 'Timeout!') {
                throw new Error('请求超时');
            }
            return response.json(); // 假设 fetch 成功后我们想处理响应数据
        })
        .catch(error => {
            console.error('请求出错:', error.message);
        });
}

// 假设我们有一个API请求,希望在5秒内完成,否则视为超时
requestWithTimeout('https://api.example.com/data', 5000)
    .then(data => console.log('获取到的数据:', data))
    .catch(error => console.error('请求失败:', error));
  • Promise.resolve():直接创建一个fulfilled状态的Promise。
  • Promise.reject():直接创建一个rejected状态的Promise。

六、应用示例

网络请求

function fetchData(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();
        xhr.open("GET", url);
        xhr.onload = () => {
            if (xhr.status === 200) {
                resolve(xhr.responseText);
            } else {
                reject(xhr.statusText);
            }
        };
        xhr.onerror = () => reject(xhr.statusText);
        xhr.send();
    });
}

fetchData("https://api.example.com/data")
    .then(data => console.log(data))
    .catch(error => console.error(error));
分类: 前端 标签: TypeScript异步Promise

评论

暂无评论数据

暂无评论数据

目录