如何将JS中Excel转JSON的局部变量inputData移至全局以跨文件导入
解决方案
因为inputData是在异步回调(fileReader.onload)里生成的,没法直接同步拿到顶级作用域再导出——异步代码执行时机晚于顶级作用域代码,直接移到顶级的话初始值是undefined,后续赋值也不会自动通知其他模块。下面给几个实用的解决思路:
方案1:导出Promise对象
把数据的获取逻辑包装成Promise,其他模块通过then或await拿到异步生成的inputData:
let selectedFile; // 顶级作用域定义Promise用于导出 export const inputDataPromise = new Promise((resolve) => { document.getElementById('button').addEventListener('click', () => { if (selectedFile) { const fileReader = new FileReader(); fileReader.readAsBinaryString(selectedFile); fileReader.onload = (event) => { const data = event.target.result; const workbook = XLSX.read(data, { type: "binary" }); const rowObject = XLSX.utils.sheet_to_row_object_array(workbook.Sheets.Grid); const newData = rowObject.filter((item, index) => { return index === rowObject.findIndex((obj) => { return JSON.stringify(item) === JSON.stringify(obj); }); }); newData.pop(); const inputData = JSON.stringify(newData, undefined, 4); console.log(inputData); // 异步完成后传递数据 resolve(inputData); }; } }); }); document.getElementById('input').addEventListener('change', (event) => { selectedFile = event.target.files[0]; });
其他文件使用:
import { inputDataPromise } from './你的文件名.js'; // 用await(需要在async函数里) async function useData() { const inputData = await inputDataPromise; // 在这里处理inputData console.log(inputData); } // 或者用then inputDataPromise.then(inputData => { console.log(inputData); });
方案2:导出顶级变量+自定义事件通知
在顶级作用域定义inputData变量导出,同时通过自定义事件通知其他模块数据已准备好:
let selectedFile; // 顶级变量,初始为null export let inputData = null; // 导出监听函数,方便其他模块等待数据 export function listenInputDataReady(callback) { // 如果数据已存在,直接回调 if (inputData) { callback(inputData); return; } // 否则监听自定义事件 document.addEventListener('inputDataReady', (e) => { callback(e.detail); }); } document.getElementById('input').addEventListener('change', (event) => { selectedFile = event.target.files[0]; }); document.getElementById('button').addEventListener('click', () => { if (selectedFile) { const fileReader = new FileReader(); fileReader.readAsBinaryString(selectedFile); fileReader.onload = (event) => { const data = event.target.result; const workbook = XLSX.read(data, { type: "binary" }); const rowObject = XLSX.utils.sheet_to_row_object_array(workbook.Sheets.Grid); const newData = rowObject.filter((item, index) => { return index === rowObject.findIndex((obj) => { return JSON.stringify(item) === JSON.stringify(obj); }); }); newData.pop(); inputData = JSON.stringify(newData, undefined, 4); console.log(inputData); // 触发事件通知其他模块 document.dispatchEvent(new CustomEvent('inputDataReady', { detail: inputData })); }; } });
其他文件使用:
import { inputData, listenInputDataReady } from './你的文件名.js'; // 检查数据是否已存在 if (inputData) { handleData(inputData); } else { // 等待数据准备好 listenInputDataReady((data) => { handleData(data); }); }
方案3:导出异步获取函数
把读取Excel并生成inputData的逻辑封装成异步函数,其他模块需要时主动调用:
let selectedFile; document.getElementById('input').addEventListener('change', (event) => { selectedFile = event.target.files[0]; }); // 导出异步函数 export async function getProcessedInputData() { return new Promise((resolve, reject) => { if (!selectedFile) { reject(new Error('请先选择文件')); return; } const fileReader = new FileReader(); fileReader.readAsBinaryString(selectedFile); fileReader.onload = (event) => { const data = event.target.result; const workbook = XLSX.read(data, { type: "binary" }); const rowObject = XLSX.utils.sheet_to_row_object_array(workbook.Sheets.Grid); const newData = rowObject.filter((item, index) => { return index === rowObject.findIndex((obj) => { return JSON.stringify(item) === JSON.stringify(obj); }); }); newData.pop(); const inputData = JSON.stringify(newData, undefined, 4); console.log(inputData); resolve(inputData); }; // 处理读取错误 fileReader.onerror = (err) => { reject(err); }; }); } // 原按钮点击逻辑可以保留,也可以让其他模块触发 document.getElementById('button').addEventListener('click', async () => { try { await getProcessedInputData(); } catch (err) { console.error('处理失败:', err); } });
其他文件使用:
import { getProcessedInputData } from './你的文件名.js'; // 比如在某个按钮点击时获取数据 document.getElementById('另一个按钮').addEventListener('click', async () => { try { const inputData = await getProcessedInputData(); handleData(inputData); } catch (err) { alert(err.message); } });
内容的提问来源于stack exchange,提问作者Mwewol
相关产品推荐
相关产品推荐

