Gatsby在onCreateNode中批量用外部URL创建File节点报EPERM错误如何解决
问题根因
你代码里存在两个核心问题导致报错:
- 多余的id取值逻辑:你在遍历URL数组调用
createRemoteFileNode时,已经直接返回了文件节点的id值,Promise.all返回的responses数组内存储的就是字符串类型的id,后续再执行d.id会得到undefined,导致字段存储异常。 - 并发请求临时文件冲突:Windows系统下并发调用
createRemoteFileNode时,如果没有显式指定唯一的name参数,Gatsby自动生成的临时文件名可能出现冲突,触发EPERM权限错误。
修正后的代码
exports.onCreateNode = async ({ node, actions: { createNode, createNodeField }, createNodeId, cache, store, }) => { if (node.internal.type === 'MyType') { // 处理单URL字段 const fileNodeImageMap = await createRemoteFileNode({ url: node.imageLink, parentNodeId: node.id, createNode, createNodeId, cache, store, }); if (fileNodeImageMap) { createNodeField({ node, name: 'imageLinkFile', value: fileNodeImageMap.id }); } // 处理多URL数组字段 if (node.additionalImageLink) { // split后加trim清除URL前后多余空格,避免请求失败 const links = node.additionalImageLink.split(',').map(url => url.trim()); const additionalImages = links.map(async (url, index) => { const fileNodeImage = await createRemoteFileNode({ url: url, parentNodeId: node.id, createNode, createNodeId, cache, store, // 显式指定唯一name,避免并发请求的临时文件名冲突 name: `${node.id}-additional-img-${index}` }); return fileNodeImage?.id; }); const responses = await Promise.all(additionalImages); // 过滤掉请求失败产生的空值 const validIds = responses.filter(Boolean); if (validIds.length) { createNodeField({ node, name: 'additionalImageLinkFile', value: validIds }); } } } };
验证步骤
修改代码后执行以下命令重启服务即可:
gatsby cleangatsby develop
内容的提问来源于stack exchange,提问作者lezan
相关产品推荐
相关产品推荐

