如何实现适配浏览器与Node.js的通用Promise处理类?
实现跨浏览器与Node.js环境兼容的Promise处理模块
我来帮你搞定这个跨环境兼容的问题!你已经完成了移除DOM操作的关键步骤,接下来只需要调整模块的导出逻辑,同时优化一下代码里的this绑定,就能让这套Promise处理类完美运行在浏览器和Node.js环境中了。
核心改造思路
- 双模块系统兼容:同时支持ES模块(
import/export)和CommonJS(require/module.exports),覆盖浏览器和Node.js的加载需求 - 简化
this绑定:用箭头函数替代bind(this),让代码更简洁易读 - 保留核心功能:不改动Process、ProcessQueue、ProcessStatus的核心业务逻辑,只调整环境适配部分
修改后的完整代码
ProcessStatus.js
const ProcessStatus = Object.freeze({ INPROGRESS: 'INPROGRESS', SUCCESS: 'SUCCESS', FAILED: 'FAILED' }); // 兼容CommonJS(Node.js)和浏览器全局变量 if (typeof module !== 'undefined' && module.exports) { module.exports = ProcessStatus; } else { window.ProcessStatus = ProcessStatus; } // 保留ES模块导出 export default ProcessStatus;
Process.js
import ProcessStatus from './ProcessStatus'; class Process { constructor(invoker) { if (invoker instanceof Function) { this._promise = new Promise(invoker); } else if (invoker instanceof Promise) { this._promise = invoker; } else { throw new TypeError('Invalid invoker passed for Process constructor'); } this._status = ProcessStatus.INPROGRESS; // 用箭头函数自动绑定this,替代bind(this) this._promise.then(() => { this._status = ProcessStatus.SUCCESS; }, () => { this._status = ProcessStatus.FAILED; }); } then(resolve, reject) { return this._promise.then(resolve, reject); } catch(reject) { return this._promise.catch(reject); } getStatus() { return this._status; } } // 兼容CommonJS和浏览器全局变量 if (typeof module !== 'undefined' && module.exports) { module.exports = Process; } else { window.Process = Process; } // 保留ES模块导出 export default Process;
ProcessQueue.js
import ProcessStatus from './ProcessStatus'; import Process from './Process'; class ProcessQueue { constructor() { this._status = ProcessStatus.INPROGRESS; this._promise = new Promise((resolve, reject) => { this._resolve = resolve; this._reject = reject; }); this._processList = []; this._resolvedCount = 0; this._successCount = 0; this._failureCount = 0; // 用箭头函数定义回调,自动绑定当前实例的this this._successCallback = () => { this._resolvedCount++; this._successCount++; if (this._resolvedCount === this._processList.length) { if (this._failureCount === 0) { this._status = ProcessStatus.SUCCESS; this._resolve(); } else { this._status = ProcessStatus.FAILED; this._reject(); } } }; this._failureCallback = () => { this._resolvedCount++; this._failureCount++; if (this._resolvedCount === this._processList.length) { this._status = ProcessStatus.FAILED; this._reject(); } }; } push(process) { if (process instanceof Process || process instanceof ProcessQueue) { process.then(this._successCallback, this._failureCallback); } else { throw new TypeError('Invalid process type pushed to the queue'); } this._processList.push(process); } then(resolve, reject) { return this._promise.then(resolve, reject); } catch(reject) { return this._promise.catch(reject); } getStatus() { return this._status; } } // 兼容CommonJS和浏览器全局变量 if (typeof module !== 'undefined' && module.exports) { module.exports = ProcessQueue; } else { window.ProcessQueue = ProcessQueue; } // 保留ES模块导出 export default ProcessQueue;
跨环境使用方式
在Node.js环境(CommonJS)
const Process = require('./Process'); const ProcessQueue = require('./ProcessQueue'); const ProcessStatus = require('./ProcessStatus'); // 示例使用 const testProcess = new Process((resolve) => setTimeout(resolve, 1000)); const queue = new ProcessQueue(); queue.push(testProcess); queue.then(() => console.log(queue.getStatus()));
在浏览器环境
- ES模块方式(现代浏览器):
<script type="module"> import Process from './Process.js'; import ProcessQueue from './ProcessQueue.js'; import ProcessStatus from './ProcessStatus.js'; // 示例使用 const testProcess = new Process((resolve) => setTimeout(resolve, 1000)); const queue = new ProcessQueue(); queue.push(testProcess); queue.then(() => console.log(queue.getStatus())); </script>
- 传统全局变量方式:
<script src="./ProcessStatus.js"></script> <script src="./Process.js"></script> <script src="./ProcessQueue.js"></script> <script> // 直接使用全局变量 const testProcess = new Process((resolve) => setTimeout(resolve, 1000)); const queue = new ProcessQueue(); queue.push(testProcess); queue.then(() => console.log(queue.getStatus())); </script>
内容的提问来源于stack exchange,提问作者Abhay Jatin Doshi
相关产品推荐
相关产品推荐

