使用Node.js重命名Rails迁移文件时时间戳重复问题求助
问题原因
你的代码里的forEach是同步遍历,所有的setTimeout会在遍历完成后几乎同时被安排执行。5秒后,所有回调函数会在同一时间点触发,生成的时间戳自然完全相同。
解决方法
方法1:为每个文件设置递增的延迟时间
利用forEach的第二个参数(索引),给每个文件的延迟时间乘以索引,让它们依次执行:
function pad2(n) { return n < 10 ? "0" + n : n; } fs.readdirSync(migrationFolder).forEach(async (file, index) => { const [migrationDate, ...rest] = file.split("_"); // 每个文件的延迟时间递增5秒 setTimeout(() => { const date = new Date(); const dateName = date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds()); console.log(dateName); fs.rename( `migrate copy/${file}`, `./rename/${dateName}_${rest.join("_")}`, (err) => { if (err) console.log(err); } ); }, 5000 * (index + 1)); // 第一个文件等5秒,第二个10秒,以此类推 });
方法2:使用async/await顺序处理文件
这种方式更直观,确保每个文件处理完成并等待延迟后,再处理下一个:
const fs = require('fs').promises; // 使用promise版本的fs模块 function pad2(n) { return n < 10 ? "0" + n : n; } // 封装延迟函数 function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } async function processMigrations() { const files = fs.readdirSync(migrationFolder); for (const file of files) { const [migrationDate, ...rest] = file.split("_"); await delay(5000); // 等待5秒 const date = new Date(); const dateName = date.getFullYear().toString() + pad2(date.getMonth() + 1) + pad2(date.getDate()) + pad2(date.getHours()) + pad2(date.getMinutes()) + pad2(date.getSeconds()); console.log(dateName); try { await fs.rename( `migrate copy/${file}`, `./rename/${dateName}_${rest.join("_")}` ); } catch (err) { console.error(err); } } } processMigrations();
额外提示
如果5秒延迟太长,其实只需要确保两次时间戳生成间隔超过1秒即可(因为你的时间戳精确到秒),可以把延迟改成1000毫秒。如果需要更精确的区分,也可以在时间戳末尾加上毫秒(比如新增pad3函数处理毫秒数),但要注意Rails是否支持这种格式的迁移文件名。
内容的提问来源于stack exchange,提问作者aRtoo
相关产品推荐
相关产品推荐

