JavaScript模块化库变量初始化及异步加载时序问题
Let's break down what's going wrong here and fix it step by step — your code has a few key issues around async timing, variable scoping, and data structure that are preventing it from working correctly:
Key Problems in Your Current Code
Async Timing Mismatch
You’re callinglibraryModule.init()immediately after starting the async load ofarVals, but the request hasn’t finished yet. This means you’re passing an emptyarValsobject toinitinstead of the loaded data.Misused
thisand Closure Variables
Yourinitfunction tries to assign values tothis.arVals, but when you calllibraryModule.init(),thispoints to the publiclibraryModuleobject — not the private closure variables (var arVals = {};) inside your IIFE. Later,execValidationtries to fetch values viathis, creating a disconnect between the private state and public methods.Data Structure Misalignment
You’ve definedrulesas an array, but you’re trying to access it with a stringruleID(like"Rule1"). Arrays use numeric indexes, so this lookup will fail unless your rule IDs are numbers.
Fixed & Refactored Code
Let’s rewrite each part to fix these issues:
1. Updated libraryModule (Fixed Scoping & Data Structure)
var libraryModule = (function () { // Private closure variables to hold state var arVals = {}; var webFormData = {}; var rules = {}; // Changed to object for string ruleID lookups function init(_arVals, _webFormData, _rules) { // Directly update private closure variables (no this needed) arVals = _arVals; webFormData = _webFormData; rules = _rules; } function execValidation(ruleID) { var arVal = arVals[ruleID]; var rule = rules[ruleID]; // Add basic error checking to avoid silent failures if (!arVal) { console.warn(`No arVal found for rule ID: ${ruleID}`); return; } if (!rule) { console.warn(`No rule configuration found for rule ID: ${ruleID}`); return; } // Log values (add your actual validation logic here) console.log('arVal:', arVal); console.log('Form Data:', webFormData); console.log('Rule:', rule); } return { execValidation: execValidation, init: init }; })();
2. Fixed Async Call Order in main.html
We’ll wait for arVals to finish loading before initializing the library and running validation:
<script> var webFormData = {}; // Replace with your actual form data var rules = { "Rule1": { /* Your rule configuration here */ } }; // Wait for async arVals load to complete first ruleConfigModule.init(function (loadedArVals) { // Now we have the loaded data — initialize the library libraryModule.init(loadedArVals, webFormData, rules); // Run validation once everything is ready libraryModule.execValidation("Rule1"); }); </script>
3. Improved ruleConfigModule (Added Error Handling)
Let’s add error handling to catch network issues or invalid JSON:
var ruleConfigModule = (function () { function init(callback, errorCallback) { loadJSON(callback, errorCallback); } function loadJSON(onSuccess, onError) { var xobj = new XMLHttpRequest(); xobj.overrideMimeType("application/json"); xobj.open('GET', 'http://localhost/test/config.json', true); xobj.onreadystatechange = function () { if (xobj.readyState === 4) { if (xobj.status === 200) { try { var json = JSON.parse(xobj.responseText); onSuccess(json); } catch (e) { onError('Failed to parse JSON: ' + e.message); } } else { onError(`HTTP Error: ${xobj.status}`); } } }; xobj.onerror = function() { onError('Network error: Unable to load config'); }; xobj.send(); } return { init: init }; })();
Optional: Modern Async with Promises/Await
For cleaner async code, you can refactor ruleConfigModule to return a Promise and use async/await:
var ruleConfigModule = (function () { function init() { return new Promise((resolve, reject) => { loadJSON(resolve, reject); }); } // Reuse the same loadJSON function from above function loadJSON(onSuccess, onError) { /* ... */ } return { init: init }; })();
Then in main.html:
<script> var webFormData = {}; var rules = { "Rule1": {} }; async function runValidation() { try { const arVals = await ruleConfigModule.init(); libraryModule.init(arVals, webFormData, rules); libraryModule.execValidation("Rule1"); } catch (error) { console.error('Validation workflow failed:', error); } } runValidation(); </script>
内容的提问来源于stack exchange,提问作者user3232760

