热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

深入解析Promise:流程与源码实现

本文探讨了异步编程的发展历程,从最初的AJAX异步回调到现代的Promise、Generator+Co以及Async/Await等技术。文章详细分析了Promise的工作原理及其源码实现,帮助开发者更好地理解和使用这一重要工具。

异步编程的发展历程

早期的异步编程主要依赖于AJAX异步回调,即在异步请求中嵌入一个回调函数来处理响应。这种方法虽然实现了基本的异步功能,但也带来了诸如“回调地狱”等问题。随着技术的发展,Promise、Generator+Co以及Async/Await等更先进的解决方案逐渐出现,极大地简化了异步编程的复杂性。

源码解析

// 基本Promise用法
let promise = new Promise((resolve, reject) => {
// 执行函数,包含成功和失败两种情况
});
promise.then(
(res) => { /* 处理成功 */ },
(err) => { /* 处理失败 */ }
);
// 以下是Promise的核心实现
function Promise(executor) {
let self = this;
self.status = 'pending'; // 初始状态
self.value = undefined; // 成功时的值
self.reason = undefined; // 失败时的原因
function resolve(value) {
if (self.status === 'pending') {
self.value = value;
self.status = 'resolved';
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason;
self.status = 'rejected';
}
}
executor(resolve, reject);
}
// 实现then方法
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this;
if (self.status === 'resolved') {
onFulfilled(self.value);
}
if (self.status === 'rejected') {
onRejected(self.reason);
}
};
// 导出模块
module.exports = Promise;

异步处理的改进

实际应用中,异步操作通常不会立即完成,因此需要对上述代码进行改进,以支持异步操作。

// 引入回调队列
function Promise(executor) {
let self = this;
self.status = 'pending';
self.value = undefined;
self.reason = undefined;
self.OnResolvedCallbacks= [];
self.OnRejectedCallbacks= [];
function resolve(value) {
if (self.status === 'pending') {
self.value = value;
self.status = 'resolved';
self.onResolvedCallbacks.forEach(fn => fn());
}
}
function reject(reason) {
if (self.status === 'pending') {
self.reason = reason;
self.status = 'rejected';
self.onRejectedCallbacks.forEach(fn => fn());
}
}
executor(resolve, reject);
}
// 改进then方法
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this;
if (self.status === 'pending') {
self.onResolvedCallbacks.push(() => onFulfilled(self.value));
self.onRejectedCallbacks.push(() => onRejected(self.reason));
}
if (self.status === 'resolved') {
onFulfilled(self.value);
}
if (self.status === 'rejected') {
onRejected(self.reason);
}
};

小结:为了确保异步操作的正确执行,每个Promise的then方法都需要将回调函数放入队列中,待状态改变时依次执行。此外,为了符合Promises/A+规范,所有操作应包裹在setTimeout中,以确保异步执行。

进一步完善Promise实现

除了基本的异步处理外,还需要考虑一些特殊情况,如异常处理、链式调用等。

// 异常处理
function Promise(executor) {
try {
executor(resolve, reject);
} catch (e) {
reject(e);
}
}
// 链式调用
Promise.prototype.then = function(onFulfilled, onRejected) {
let self = this;
let promise2;
if (self.status === 'resolved') {
promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
onFulfilled(self.value);
});
});
}
if (self.status === 'rejected') {
promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
onRejected(self.reason);
});
});
}
if (self.status === 'pending') {
promise2 = new Promise((resolve, reject) => {
self.onResolvedCallbacks.push(() => {
onFulfilled(self.value);
});
self.onRejectedCallbacks.push(() => {
onRejected(self.reason);
});
});
}
return promise2;
};
// 处理返回自身和其他特殊情况
function resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError('循环引用'));
}
let called;
if ((x !== null) && (typeof x === 'object' || typeof x === 'function')) {
try {
let then = x.then;
if (typeof then === 'function') {
then.call(x, y => {
if (called) return;
called = true;
resolvePromise(promise2, y, resolve, reject);
}, err => {
if (called) return;
called = true;
reject(err);
});
} else {
resolve(x);
}
} catch (e) {
if (called) return;
called = true;
reject(e);
}
} else {
resolve(x);
}
}
// 测试Promise是否符合规范
npm install -g promises-aplus-tests
promises-aplus-tests ./Promise.js

扩展内容

除了基本的Promise实现,还有一些高级技巧可以帮助开发者更好地利用这一工具。

高阶函数

// 判断数据类型
function isType(type) {
return function(content) {
return Object.prototype.toString.call(content) === `[object ${type}]`;
};
}
let isString = isType('String');
let isArray = isType('Array');
console.log(isArray('hello')); // false
// 预置函数
function after(times, callback) {
return function() {
if (--times === 0) {
callback();
}
};
}
let eat = after(3, () => {
console.log('不吃了');
});
eat(); // 没打印
eat(); // 没打印
eat(); // 打印 '不吃了'

通过这些高阶函数,可以更灵活地处理各种编程任务,提高代码的复用性和可维护性。


推荐阅读
  • 基于Node.js、Express、MongoDB和Socket.io的实时聊天应用开发
    本文详细介绍了使用Node.js、Express、MongoDB和Socket.io构建的实时聊天应用程序。涵盖项目结构、技术栈选择及关键依赖项的配置。 ... [详细]
  • 本文详细介绍了如何在PHP中进行数组删除、清空等操作,并提供了在Visual Studio Code中创建PHP文件的步骤。 ... [详细]
  • 深入解析Java虚拟机(JVM)架构与原理
    本文旨在为读者提供对Java虚拟机(JVM)的全面理解,涵盖其主要组成部分、工作原理及其在不同平台上的实现。通过详细探讨JVM的结构和内部机制,帮助开发者更好地掌握Java编程的核心技术。 ... [详细]
  • 在高并发需求的C++项目中,我们最初选择了JsonCpp进行JSON解析和序列化。然而,在处理大数据量时,JsonCpp频繁抛出异常,尤其是在多线程环境下问题更为突出。通过分析发现,旧版本的JsonCpp存在多线程安全性和性能瓶颈。经过评估,我们最终选择了RapidJSON作为替代方案,并实现了显著的性能提升。 ... [详细]
  • 深入解析动态代理模式:23种设计模式之三
    在设计模式中,动态代理模式是应用最为广泛的一种代理模式。它允许我们在运行时动态创建代理对象,并在调用方法时进行增强处理。本文将详细介绍动态代理的实现机制及其应用场景。 ... [详细]
  • 本题要求在一组数中反复取出两个数相加,并将结果放回数组中,最终求出最小的总加法代价。这是一个经典的哈夫曼编码问题,利用贪心算法可以有效地解决。 ... [详细]
  • 深入剖析JVM垃圾回收机制
    本文详细探讨了Java虚拟机(JVM)中的垃圾回收机制,包括其意义、对象判定方法、引用类型、常见垃圾收集算法以及各种垃圾收集器的特点和工作原理。通过理解这些内容,开发人员可以更好地优化内存管理和程序性能。 ... [详细]
  • 本文详细探讨了Java中的ClassLoader类加载器的工作原理,包括其如何将class文件加载至JVM中,以及JVM启动时的动态加载策略。文章还介绍了JVM内置的三种类加载器及其工作方式,并解释了类加载器的继承关系和双亲委托机制。 ... [详细]
  • 黑马头条项目:Vue 文章详情模块与交互功能实现
    本文详细介绍了如何在黑马头条项目中配置文章详情模块的路由、获取和展示文章详情数据,以及实现关注、点赞、不喜欢和评论功能。通过这些步骤,您可以全面了解如何开发一个完整的前端文章详情页面。 ... [详细]
  • 深入解析SpringMVC核心组件:DispatcherServlet的工作原理
    本文详细探讨了SpringMVC的核心组件——DispatcherServlet的运作机制,旨在帮助有一定Java和Spring基础的开发人员理解HTTP请求是如何被映射到Controller并执行的。文章将解答以下问题:1. HTTP请求如何映射到Controller;2. Controller是如何被执行的。 ... [详细]
  • JavaScript中的数组是数据集合的核心结构之一,内置了多种实用的方法。掌握这些方法不仅能提高开发效率,还能显著提升代码的质量和可读性。本文将详细介绍数组的创建方式及常见操作方法。 ... [详细]
  • 主调|大侠_重温C++ ... [详细]
  • 本文深入探讨了MySQL中常见的面试问题,包括事务隔离级别、存储引擎选择、索引结构及优化等关键知识点。通过详细解析,帮助读者在面对BAT等大厂面试时更加从容。 ... [详细]
  • 本文深入探讨了UNIX/Linux系统中的进程间通信(IPC)机制,包括消息传递、同步和共享内存等。详细介绍了管道(Pipe)、有名管道(FIFO)、Posix和System V消息队列、互斥锁与条件变量、读写锁、信号量以及共享内存的使用方法和应用场景。 ... [详细]
  • 本文档汇总了Python编程的基础与高级面试题目,涵盖语言特性、数据结构、算法以及Web开发等多个方面,旨在帮助开发者全面掌握Python核心知识。 ... [详细]
author-avatar
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有