当我通过next_cursor进行分页时,每次通过NodeJS函数访问URL时,都会获得不同数量的频道。
获取的总通道数是7488,而另一个则是300。每次运行该程序时都不同。
URL : https://slack.com/api/conversations.list?types=public_channel&cursor={cursor}=&exclude_archived=true&token={token}
问题是由于速率限制所致。 session.list属于第二层速率限制。每分钟最多只能有20个请求。
function fetchData(){
getResponse(url);
function getResponse(url) {
let tempData = '';
https.get(url, (resp) => {
resp.on('data', (chunk) => {
tempData += chunk;
});
resp.on('end', () => {
try{
tempData = JSON.parse(tempData);
if(tempData.channels){
resultData.push(tempData.channels);
}
if (tempData.response_metadata && tempData.response_metadata.next_cursor) {
if(tempData.response_metadata.next_cursor === ''){
return resultData;
}
let cursorIndex = url.indexOf('cursor');
let newUrl = url.slice(0,cursorIndex);
let token = apiConstants.SLACK_API['ACCESS_TOKEN'];
let nextCursor = tempData.response_metadata.next_cursor.slice(0,tempData.response_metadata.next_cursor.length-1);
nextCursor = nextCursor + "%3D";
newUrl = newUrl + 'cursor=' + nextCursor + '&token='+ token;
getResponse(newUrl);
} else {
return resultData;
}
}catch(err){ console.log(err);} } } }
答案 0 :(得分:0)
可靠地做到这一点的一种方法是使用Node Slack SDK的WebClient
,它在游标分页的方法(例如conversations.list
)上具有自动分页功能。它还通过将请求排队Slack响应指示的时间量来自动处理速率限制。免责声明:我在Slack工作,并对此软件包做出了贡献。
文档涵盖了自动分页支持的详细信息:https://slack.dev/node-slack-sdk/web_api#pagination。如果仅将web.conversations.history()
替换为web.conversations.list()
,则第一个示例可用于获取频道的完整列表。
我们不建议您再使用此技术,因为这种情况非常罕见,您实际上需要整个列表。实际上,自动分页将在即将发布的下一个主要版本(v5.0.0)中删除。但是,如果这确实是您想要做的(如您的问题所示),那么您应该查看该部分的第二个示例。我已经在下面复制了它:
const { WebClient } = require('@slack/client');
// An access token (from your Slack app or custom integration - xoxp, or xoxb)
const token = process.env.SLACK_TOKEN;
const web = new WebClient(token);
async function getAllChannels(options) {
async function pageLoaded(accumulatedChannels, res) {
// Merge the previous result with the results in the current page
const mergedChannels = accumulatedChannels.concat(res.channels);
// When a `next_cursor` exists, recursively call this function to get the next page.
if (res.response_metadata && res.response_metadata.next_cursor && res.response_metadata.next_cursor !== '') {
// Make a copy of options
const pageOptions = { ...options };
// Add the `cursor` argument
pageOptions.cursor = res.response_metadata.next_cursor;
return pageLoaded(mergedChannels, await web.conversations.list(pageOptions));
}
// Otherwise, we're done and can return the result
return mergedChannels;
}
return pageLoaded([], await web.conversations.list(options));
}
(async () => {
const allChannels = await getAllChannels({ exclude_archived: true, types: 'public_channel' });
console.log(allChannels);
})();
PS。在版本v5.0.0中,我们计划包括a helper method that will make this much simpler。现在,第二个示例是最向前兼容的方法,我建议您在v5.0.0发布后将其重构为使用助手。