我是一个小团队的一员,在一个相当小的网站上工作,该网站拥有用户帐户;此时大约有100名用户。我们正在使用 Amazon Cognito 进行用户管理。我们的网站上有一个摘要页面,其中显示所有用户和各种属性的列表/表格。然而,有一个硬性限制 https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ListUsers.htmlAmazon Cognito listUsers API 调用返回的项目数,在本例中为 60。
幸运的是,API 调用还会返回一个令牌,以便在有更多用户时用于进行后续调用。使用这些令牌,我们能够请求所有用户的完整列表。
此外,我们的网站使用react-redux 和 javascript 库 bluebird。在此问题的上下文中,请求所有用户列表的组件还会调度操作(redux 部分),并且来自 Amazon aws-sdk 的 CognitoIdentityServiceProvider 被传递到 bluebird Promise.promisfyAll (将异步后缀添加到 listUser 调用)。我正在修改此组件以获取完整的用户列表。
作为请求整个用户列表的草稿,我使用递归函数将 Promise 链接在一起,直到从 Amazon 返回的分页标记未定义并将结果存储在某些类变量中。我用过这个论坛帖子作为参考。 https://develop.zendesk.com/hc/en-us/community/posts/360004239687-Pagination-using-JavaScript-Promises
这可行,但我对实施感觉不太好;目前在我们的用例中应该没问题,因为我们有大约 100 个用户,但我不知道这是否可以很好地扩展到数千个或更多用户。我对递归的理解足够危险,因为我不知道当承诺/调用数量增加时这种技术是否会导致问题。我想到了开销和内存管理的问题。然而,我们至少在一段时间内不必担心用户数量飙升至数千,但我仍然想了解实现相同目标的潜在更好和/或更安全的方法。
以下片段来自请求用户列表的组件:
import Promise from 'bluebird';
import { CognitoIdentityServiceProvider } from './services/aws';
export const fetchRegisteredUsers = () => (dispatch) => {
...
let allUsersTemp = [];
let paginationToken;
const getUserList = () => {
let tempUserTest = CognitoIdentityServiceProvider.listUsersAsync({
UserPoolId: process.env.COGNITO_USER_POOL_ID,
PaginationToken: paginationToken
});
return tempUserTest.then((tempUser) => {
allUsersTemp = allUsersTemp.concat(tempUser.Users);
paginationToken = tempUser.PaginationToken;
if(paginationToken) {
return getUserList();
} else {
return;
}
})
}
const adminUsers = CognitoIdentityServiceProvider.listUsersInGroupAsync(adminParams);
return Promise.all([adminUsers]).then(
([{ Users: adminUsers }]) => {
getUserList().then((item) => {
let allUsers = allUsersTemp;
const adminUsernames = adminUsers.map(user => user.Username);
allUsers.forEach(user => {
let mappedAttributes = {};
user.Attributes.forEach(attribute => mappedAttributes[attribute.Name] = attribute.Value);
user.Attributes = mappedAttributes;
user.isAdmin = adminUsernames.includes(user.Username);
});
dispatch({
type: FETCH_REGISTERED_USERS_SUCCESS,
payload: allUsers
});
});
}, ...
据我了解,bluebird Promise.all 调用会等待,直到传递给它的每个项目都可以解析,然后再执行 .then 部分中的内容;在对代码进行任何更改之前,有两个列表,一个用于用户,一个用于管理员。 Promise.all 等待两个 Promise 完成,对数据进行一些基本处理,并在操作调度有效负载中返回数据。
经过我的更改,处理和返回用户列表的逻辑是在递归承诺链(getUserList)完成后执行的。
我的问题:这个技术可以吗?我可以按原样使用它吗?或者它是否不安全?如果是,问题具体是什么?还有更好的方法吗?
我的弱点是递归和承诺/蓝鸟,所以请随意批评与这些主题相关的任何代码