如何从异步Promise提取数组,供同步代码及其他方法访问?
First off, let's clarify: your current approach of exporting the Promise from fileA.js is actually a valid way to handle asynchronous database results. The key thing to remember is you can't access asynchronous results synchronously—any code that needs to use shiftR has to wait for the Promise to resolve, either via .then() or async/await.
Let's refine your implementation to make it more robust and reusable:
1. Cache the Promise to Avoid Duplicate Database Requests
Right now, every time you require('./fileA'), it will re-run the database requests. To fix this, cache the Promise so it only executes once, and all modules share the resolved result:
fileA.js
require('dotenv').config() const knex = require('knex') const knexInstance = knex({ client: 'pg', connection: process.env.DB_URL, }) const days = ["monday", "tuesday", "wednesday"]; function dbRequest(day){ console.log(`Day: ${day}`); return knexInstance.select('shift_time', day).from('shr'); } // Cache the Promise so we only hit the database once const shiftRPromise = Promise.all(days.map(day => dbRequest(day))) .then(results => ({ shiftR: results })); module.exports = shiftRPromise;
fileB.js (usage stays similar, but now it reuses the cached result)
const shiftRProm = require('./fileA'); // Using .then() shiftRProm.then(({ shiftR }) => { console.log('Shift data:', shiftR); // Your logic using shiftR goes here }); // Or using async/await (cleaner for longer code) async function useShiftData() { const { shiftR } = await shiftRProm; console.log('Shift data:', shiftR); // Do something with shiftR } useShiftData();
2. Export an Async Function for On-Demand Requests
If you need to occasionally refresh the data or trigger the request manually instead of running it on module load, export an async function instead:
fileA.js
require('dotenv').config() const knex = require('knex') const knexInstance = knex({ client: 'pg', connection: process.env.DB_URL, }) const days = ["monday", "tuesday", "wednesday"]; function dbRequest(day){ console.log(`Day: ${day}`); return knexInstance.select('shift_time', day).from('shr'); } // Async function to fetch data on demand async function getShiftData() { const results = await Promise.all(days.map(day => dbRequest(day))); return { shiftR: results }; } // Optional: still cache the first request if needed const cachedShiftData = getShiftData(); module.exports = { getShiftData, cachedShiftData };
Usage in other files
const { getShiftData, cachedShiftData } = require('./fileA'); // For fresh data every time async function refreshAndUse() { const { shiftR } = await getShiftData(); // Use fresh shift data } // For cached data (only one database call) async function useCachedData() { const { shiftR } = await cachedShiftData; // Use cached shift data }
Why Your Previous Export Worked (and Common Pitfalls)
Your original code was actually functional—if you ran fileB.js, it would log the correct shiftR once the Promise resolved. The most common mistake here is trying to access the result synchronously, like:
// ❌ This won't work! shiftRProm is a Promise, not the resolved value const shiftRProm = require('./fileA'); console.log(shiftRProm.shiftR); // Undefined
All code that relies on shiftR must be wrapped in a .then() handler or inside an async function using await.
内容的提问来源于stack exchange,提问作者ezg

