从递归获取中解包所有承诺
unwrapping all promises from a recursive fetch
我正在尝试创建一个递归函数,returns 给定块的所有子块。
关于一些背景信息,我正在使用概念 API 从页面中获取所有块。
一个块可以有块的子块,这些子块也可以有块的子块。
这就是为什么我需要一个递归函数来检查所有块。
其实我已经成功的从google appscript做了一个递归函数,如下
// recursive function to get all nested blocks in a flattened array format
function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`
let options = {
"async": true,
"crossDomain": true,
"method": "get",
"headers": {
"Authorization": `Bearer ${NOTION_API_KEY}`,
"Notion-Version": "2022-02-22",
"Content-Type": "application/json"
}
};
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());;
console.log(response)
let blocks = response.results
Utilities.sleep(50)
// guard clause
if (blocks.length == 0) {
return
}
blocks = blocks.concat(blocks.map((block) => getSubBlocks(block.id)).flat())
// get rid of undefined
blocks = blocks.filter(block => block != undefined)
return blocks
}
我正在尝试从 node.js 中创建一个相同的函数,但我在展开所有块时遇到了问题。
下面是递归函数的node-js版本
import fetch from "node-fetch";
// recursive function to get all nested blocks in a flattened array format
async function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`;
let options = {
async: true,
crossDomain: true,
method: "get",
headers: {
Authorization: `Bearer ${NOTION_API_KEY}`,
"Notion-Version": "2022-02-22",
"Content-Type": "application/json",
},
};
const response = await fetch(url, options);
const r = await response.json();
let blocks = r.results;
// guard clause ends the function if the array is empty
if (blocks.length == 0) {
return;
}
// for each block objects, check for children blocks in a recursive manner
let newBlocks = await blocks
.map(async (block) => await getSubBlocks(block.id))
.flat();
blocks = blocks.concat(newBlocks);
// get rid of undefined
blocks = blocks.filter((block) => block != undefined);
return await blocks;
}
getSubBlocks(testBlock)
.then((r) => console.log(r))
.catch((error) => console.log(error));
我明白上面的函数是一个异步函数,所以它总是returns一个承诺。
这就是为什么我试图用 then 子句解包 promise,但我只解包了第一个块,而递归调用的其他块仍然作为 promise 呈现。
示例输出如下:
[
{
object: 'block',
id: 'XXXXXXXXXXXX',
created_time: '2022-05-28T05:15:00.000Z',
last_edited_time: '2022-05-28T05:15:00.000Z',
created_by: { object: 'user', id: 'XXXXXX' },
last_edited_by: { object: 'user', id: 'XXXXXX' },
has_children: false,
archived: false,
type: 'paragraph',
paragraph: { rich_text: [Array], color: 'default' }
},
{
object: 'block',
id: 'XXXXXXXXXXXX',
created_time: '2022-05-28T05:15:00.000Z',
last_edited_time: '2022-05-28T05:15:00.000Z',
created_by: { object: 'user', id: 'XXXXXXXXXXXX' },
last_edited_by: { object: 'user', id: 'XXXXXXXXXXXX' },
has_children: false,
archived: false,
type: 'paragraph',
paragraph: { rich_text: [], color: 'default' }
},
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
]
有什么办法可以解决这个问题吗?
从更广泛的意义上讲,在使用递归和获取时是否有任何最佳实践来检索所有值?
您的 getSubBlocks
函数不 return Promise
。
此外,您可能希望将方法从 map
更改为正常的 for...of
循环以简化代码并删除一些不必要的 await
.
试试这个方法:
import fetch from 'node-fetch';
// recursive function to get all nested blocks in a flattened array format
async function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`;
let options = {
async: true,
crossDomain: true,
method: 'get',
headers: {
Authorization: `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-02-22',
'Content-Type': 'application/json',
},
};
const response = await fetch(url, options);
const r = await response.json();
let blocks = r.results;
// guard clause ends the function if the array is empty
if (blocks && blocks.length == 0) {
return undefined;
}
// for each block objects, check for children blocks in a recursive manner
for (const block of blocks) {
const subBlocks = await getSubBlocks(block.id)
if (subBlocks) blocks = [...blocks, ...subBlocks]
}
return blocks;
}
const res = getSubBlocks(testBlock)
我正在尝试创建一个递归函数,returns 给定块的所有子块。
关于一些背景信息,我正在使用概念 API 从页面中获取所有块。 一个块可以有块的子块,这些子块也可以有块的子块。 这就是为什么我需要一个递归函数来检查所有块。
其实我已经成功的从google appscript做了一个递归函数,如下
// recursive function to get all nested blocks in a flattened array format
function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`
let options = {
"async": true,
"crossDomain": true,
"method": "get",
"headers": {
"Authorization": `Bearer ${NOTION_API_KEY}`,
"Notion-Version": "2022-02-22",
"Content-Type": "application/json"
}
};
var response = JSON.parse(UrlFetchApp.fetch(url, options).getContentText());;
console.log(response)
let blocks = response.results
Utilities.sleep(50)
// guard clause
if (blocks.length == 0) {
return
}
blocks = blocks.concat(blocks.map((block) => getSubBlocks(block.id)).flat())
// get rid of undefined
blocks = blocks.filter(block => block != undefined)
return blocks
}
我正在尝试从 node.js 中创建一个相同的函数,但我在展开所有块时遇到了问题。 下面是递归函数的node-js版本
import fetch from "node-fetch";
// recursive function to get all nested blocks in a flattened array format
async function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`;
let options = {
async: true,
crossDomain: true,
method: "get",
headers: {
Authorization: `Bearer ${NOTION_API_KEY}`,
"Notion-Version": "2022-02-22",
"Content-Type": "application/json",
},
};
const response = await fetch(url, options);
const r = await response.json();
let blocks = r.results;
// guard clause ends the function if the array is empty
if (blocks.length == 0) {
return;
}
// for each block objects, check for children blocks in a recursive manner
let newBlocks = await blocks
.map(async (block) => await getSubBlocks(block.id))
.flat();
blocks = blocks.concat(newBlocks);
// get rid of undefined
blocks = blocks.filter((block) => block != undefined);
return await blocks;
}
getSubBlocks(testBlock)
.then((r) => console.log(r))
.catch((error) => console.log(error));
我明白上面的函数是一个异步函数,所以它总是returns一个承诺。 这就是为什么我试图用 then 子句解包 promise,但我只解包了第一个块,而递归调用的其他块仍然作为 promise 呈现。 示例输出如下:
[
{
object: 'block',
id: 'XXXXXXXXXXXX',
created_time: '2022-05-28T05:15:00.000Z',
last_edited_time: '2022-05-28T05:15:00.000Z',
created_by: { object: 'user', id: 'XXXXXX' },
last_edited_by: { object: 'user', id: 'XXXXXX' },
has_children: false,
archived: false,
type: 'paragraph',
paragraph: { rich_text: [Array], color: 'default' }
},
{
object: 'block',
id: 'XXXXXXXXXXXX',
created_time: '2022-05-28T05:15:00.000Z',
last_edited_time: '2022-05-28T05:15:00.000Z',
created_by: { object: 'user', id: 'XXXXXXXXXXXX' },
last_edited_by: { object: 'user', id: 'XXXXXXXXXXXX' },
has_children: false,
archived: false,
type: 'paragraph',
paragraph: { rich_text: [], color: 'default' }
},
Promise { <pending> },
Promise { <pending> },
Promise { <pending> },
]
有什么办法可以解决这个问题吗?
从更广泛的意义上讲,在使用递归和获取时是否有任何最佳实践来检索所有值?
您的 getSubBlocks
函数不 return Promise
。
此外,您可能希望将方法从 map
更改为正常的 for...of
循环以简化代码并删除一些不必要的 await
.
试试这个方法:
import fetch from 'node-fetch';
// recursive function to get all nested blocks in a flattened array format
async function getSubBlocks(blockId) {
const url = `https://api.notion.com/v1/blocks/${blockId}/children?page_size=100`;
let options = {
async: true,
crossDomain: true,
method: 'get',
headers: {
Authorization: `Bearer ${NOTION_API_KEY}`,
'Notion-Version': '2022-02-22',
'Content-Type': 'application/json',
},
};
const response = await fetch(url, options);
const r = await response.json();
let blocks = r.results;
// guard clause ends the function if the array is empty
if (blocks && blocks.length == 0) {
return undefined;
}
// for each block objects, check for children blocks in a recursive manner
for (const block of blocks) {
const subBlocks = await getSubBlocks(block.id)
if (subBlocks) blocks = [...blocks, ...subBlocks]
}
return blocks;
}
const res = getSubBlocks(testBlock)