《前端开发之promise》

298 阅读2分钟

1. Promise 基本概念

Promise 是一个代表异步操作最终完成或失败的对象。它有三种状态:

  • pending(进行中)

  • fulfilled(已成功)

  • rejected(已失败)

2. 基本用法

// 创建 Promise
const promise = new Promise((resolve, reject) => {
    // 异步操作
    setTimeout(() => {
        const random = Math.random();
        if (random > 0.5) {
            resolve('success');
        } else {
            reject('error');
        }
    }, 1000);
});

// 处理 Promise
promise
    .then(result => console.log(result))
    .catch(error => console.error(error))
    .finally(() => console.log('完成'));

3. Promise 链式调用

// 链式处理示例
function step1() {
    return new Promise(resolve => {
        setTimeout(() => resolve('步骤1完成'), 1000);
    });
}

function step2(data) {
    return new Promise(resolve => {
        setTimeout(() => resolve(data + ' -> 步骤2完成'), 1000);
    });
}

step1()
    .then(result => step2(result))
    .then(finalResult => console.log(finalResult))
    .catch(error => console.error(error));

4. Promise 静态方法

4.1 Promise.all()

// 并行执行多个 Promise
const promises = [
    fetch('/api/users'),
    fetch('/api/posts'),
    fetch('/api/comments')
];

Promise.all(promises)
    .then(([users, posts, comments]) => {
        // 所有请求都成功完成
    })
    .catch(error => {
        // 任一请求失败
    });

4.2 Promise.race()

// 竞态处理
const timeout = new Promise((_, reject) => 
    setTimeout(() => reject('timeout'), 5000)
);

const fetchData = fetch('/api/data');

Promise.race([fetchData, timeout])
    .then(result => console.log(result))
    .catch(error => console.error(error));

4.3 Promise.allSettled()

// 等待所有 Promise 完成(无论成功失败)
Promise.allSettled([
    fetch('/api/1'),
    fetch('/api/2'),
    fetch('/api/3')
])
.then(results => {
    results.forEach(result => {
        if (result.status === 'fulfilled') {
            console.log('成功:', result.value);
        } else {
            console.log('失败:', result.reason);
        }
    });
});

5. 实际应用场景

5.1 接口请求封装

class HttpClient {
    async get(url) {
        try {
            const response = await fetch(url);
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            return await response.json();
        } catch (error) {
            console.error('Request failed:', error);
            throw error;
        }
    }
}

5.2 图片加载

function loadImage(url) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = () => reject(new Error(`Failed to load image: ${url}`));
        img.src = url;
    });
}

5.3 延时函数

function delay(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

// 使用示例
async function animation() {
    console.log('开始');
    await delay(1000);
    console.log('1秒后');
    await delay(2000);
    console.log('再2秒后');
}

5.4 缓存控制

class Cache {
    constructor() {
        this.cache = new Map();
    }

    async get(key, fetchFn) {
        if (this.cache.has(key)) {
            return this.cache.get(key);
        }

        const data = await fetchFn();
        this.cache.set(key, data);
        return data;
    }
}

5.5 并发控制

class RequestQueue {
    constructor(maxConcurrent = 5) {
        this.queue = [];
        this.running = 0;
        this.maxConcurrent = maxConcurrent;
    }

    async add(request) {
        if (this.running >= this.maxConcurrent) {
            await new Promise(resolve => this.queue.push(resolve));
        }

        this.running++;
        try {
            return await request();
        } finally {
            this.running--;
            if (this.queue.length > 0) {
                this.queue.shift()();
            }
        }
    }
}

6. 错误处理最佳实践

async function handleAsyncOperation() {
    try {
        const result = await someAsyncOperation();
        return result;
    } catch (error) {
        // 错误分类处理
        if (error instanceof NetworkError) {
            // 处理网络错误
        } else if (error instanceof ValidationError) {
            // 处理验证错误
        } else {
            // 处理其他错误
        }
        throw error; // 重新抛出错误
    }
}

7. 性能优化

// 缓存 Promise 结果
const memoizedPromise = (() => {
    let cache = null;
    return () => {
        if (!cache) {
            cache = new Promise((resolve) => {
                // 执行耗时操作
                setTimeout(() => resolve('result'), 1000);
            });
        }
        return cache;
    };
})();

8. 注意事项

8.1 避免 Promise 嵌套:

// 不好的写法
promise1().then(result1 => {
    promise2().then(result2 => {
        promise3().then(result3 => {
            // ...
        });
    });
});

// 好的写法
promise1()
    .then(result1 => promise2())
    .then(result2 => promise3())
    .then(result3 => {
        // ...
    });

8.2 始终添加错误处理:

somePromise()
    .then(handleSuccess)
    .catch(handleError)
    .finally(cleanup);

8.3 合理使用 async/await:

// 更易读的异步代码
async function processData() {
    try {
        const data = await fetchData();
        const processed = await processResult(data);
        return processed;
    } catch (error) {
        handleError(error);
    }
}