嵌套Async/Await引发序列化错误,求问题排查方案
Next.js getStaticProps调用Notion API时的序列化错误
错误信息
Error: Error serializing `.posts[0]` returned from `getStaticProps` in "/notion". Reason: `undefined` cannot be serialized as JSON. Please use `null` or omit this value.
问题代码
export async function getStaticProps() { const postsResponse = await fetch( `https://api.notion.com/v1/databases/${process.env.BLOG_DB}/query`, { headers: { Authorization: `Bearer ${process.env.NOTION_TOKEN}`, "Notion-Version": `${process.env.NOTION_VERSION}`, }, method: "POST", }) const postsJSON = await postsResponse.json() const posts = postsJSON.results.map((post) => { const blocksResponse = await fetch( `https://api.notion.com/v1/blocks/${post.id}/children`, { headers: { Authorization: `Bearer ${process.env.NOTION_TOKEN}`, "Notion-Version": `${process.env.NOTION_VERSION}`, }, method: "GET", }) const blocksJSON = await blocksResponse.json() const blocks = blocksJSON.results.map((block) => { return { id: block.id, type: block.type, text: block[block.type].text[0].plain_text, link: block[block.type].text[0].href, } }) return { id: post.id, title: post.properties.Title.title[0].plain_text, tags: post.properties.Tags.multi_select.map(tag => tag.name), blocks: [], } }); return { props: { posts } }; }
预期目标
希望获取每篇博客的子块,返回如下结构的数组:
[ { "post_id": "id of blog post", "post_title": "title of blog post", "children": [...] // 子块数据 }, { "post_id": "id of blog post", "post_title": "title of blog post", "children": [...] // 子块数据 } ]
问题原因分析
- map回调未正确处理异步逻辑:
postsJSON.results.map的回调里用了await但没加async,导致map返回的是Promise数组而非实际数据。Next.js序列化Promise时会出错,同时内部异步请求也无法正确完成,可能产生undefined值。 - 未处理Notion块的空值场景:直接访问
block[block.type].text[0].plain_text和href,但部分Notion块(如图片、分割线)可能没有text字段,或text数组为空,这会直接生成undefined,触发序列化失败。 - 未正确赋值子块数据:当前代码返回的
blocks是空数组,没有把获取到的子块数据赋值进去,不符合预期结构。
修正后的代码
export async function getStaticProps() { const postsResponse = await fetch( `https://api.notion.com/v1/databases/${process.env.BLOG_DB}/query`, { headers: { Authorization: `Bearer ${process.env.NOTION_TOKEN}`, "Notion-Version": `${process.env.NOTION_VERSION}`, }, method: "POST", }) const postsJSON = await postsResponse.json() // 用Promise.all等待所有异步请求完成 const posts = await Promise.all(postsJSON.results.map(async (post) => { const blocksResponse = await fetch( `https://api.notion.com/v1/blocks/${post.id}/children`, { headers: { Authorization: `Bearer ${process.env.NOTION_TOKEN}`, "Notion-Version": `${process.env.NOTION_VERSION}`, }, method: "GET", }) const blocksJSON = await blocksResponse.json() const children = blocksJSON.results.map((block) => { // 处理可能没有text字段的情况,避免undefined const textContent = block[block.type]?.text?.[0] return { id: block.id, type: block.type, text: textContent?.plain_text || null, link: textContent?.href || null, } }) // 匹配预期的返回结构 return { post_id: post.id, post_title: post.properties.Title.title[0]?.plain_text || null, children: children, } })); return { props: { posts } }; }
内容的提问来源于stack exchange,提问作者Adib Kadir
相关产品推荐
相关产品推荐

