如何从 redux 操作中的递归承诺中获取结果
how to get the result from recursive promises in a redux action
我已经在网上搜索过,但找不到解决方案。我的最终目标是从 dynamodb table 中提取所有数据。问题是当 table 大于 1MB 时,在响应中我将获得一个数据块和一个 LastEvaluatedKey
参数(它提供了我可以在下一次调用中使用的索引来获取下一个块)。如果需要,scan
操作被记录在案 here。
我在我的应用程序中使用了 reactjs、redux 和 redux-thunk。
我在单一或链式格式中适度使用了 promises,但这个更具挑战性,我目前可以解决。令我困惑的是,如果没有收到先前的响应,就无法拨打新的电话,所以我认为这些电话不能同时进行。另一方面,由于 scan
操作是一个承诺(据我所知),如果我尝试 return 来自我自己的方法的承诺,该操作不会收到结果。
我很困惑,我真的很想了解如何让它发挥作用。
动作:
function getDynamodbTableRecords(tableName) {
return dispatch => {
dispatch(request());
var recordsSet = [];
var data = myAwsService.getTableRecords(tableName, null) || {Items:[]};
if (data.Items.length > 0){
data.Items.map(record => {
recordsSet.push(record);
});
dispatch(success(recordsSet));
} else {
dispatch(failure("No Records Found!"));
}
};
function request() { return { type: DATA_LOADING, selectedTable: tableName } }
function success(tableRecords) { return { type: DATA_LOAD_SUCCESS, tableRecords } }
function failure(error) { return { type: DATA_LOAD_FAILED, errors: error } }
}
myAwsService:
function getTableRecords(tableName, lastEvaluatedKey = null) {
getRecordsBatch(tableName, lastEvaluatedKey)
.then(
data => {
if (data.LastEvaluatedKey) {
return getTableRecords(tableName, data.LastEvaluatedKey)
.then(
nextData => {
data.Items = data.Items.concat(nextData.Items);
}
)
}
return data;
}
)
}
function getRecordsBatch(tableName, lastEvaluatedKey = null) {
var awsDynamodb = new DynamoDB();
let params = { TableName: tableName };
if (lastEvaluatedKey) {
params['ExclusiveStartKey'] = lastEvaluatedKey;
}
return new Promise((resolve, reject) => {
awsDynamodb.scan(params, function(err, data) {
if (err) {
reject(err);
}
return resolve(data);
});
});
}
不确定你的递归承诺是否有效,但我会这样做:
function getTableRecords(
tableName,
lastEvaluatedKey = null,
result = { Items: [] }
) {
return getRecordsBatch(tableName, lastEvaluatedKey).then(
data => {
if (data.LastEvaluatedKey) {
return getTableRecords(
tableName,
data.LastEvaluatedKey,
{
...data,
Items: result.Items.concat(data.Items),
}
);
}
return {
...data,
Items: result.Items.concat(data.Items),
};
}
);
}
该操作还应分派 data.Items 而不是 getTabelRecords returns 的承诺,如果出现问题,您可能希望分派失败操作:
function getDynamodbTableRecords(tableName) {
return async dispatch => {
dispatch(request());
//you probably want the data, not a promise of data
try {
var data = await myAwsService.getTableRecords(
tableName,
null
);
if (data.Items.length > 0) {
//no reason to have the temporary recordSet variable
dispatch(success(data.Items.map(record => record)));
} else {
dispatch(failure('No Records Found!'));
}
} catch (e) {
dispatch(failure(e.message));
}
};
function request() {
return { type: DATA_LOADING, selectedTable: tableName };
}
function success(tableRecords) {
return { type: DATA_LOAD_SUCCESS, tableRecords };
}
function failure(error) {
return { type: DATA_LOAD_FAILED, errors: error };
}
}
我已经在网上搜索过,但找不到解决方案。我的最终目标是从 dynamodb table 中提取所有数据。问题是当 table 大于 1MB 时,在响应中我将获得一个数据块和一个 LastEvaluatedKey
参数(它提供了我可以在下一次调用中使用的索引来获取下一个块)。如果需要,scan
操作被记录在案 here。
我在我的应用程序中使用了 reactjs、redux 和 redux-thunk。
我在单一或链式格式中适度使用了 promises,但这个更具挑战性,我目前可以解决。令我困惑的是,如果没有收到先前的响应,就无法拨打新的电话,所以我认为这些电话不能同时进行。另一方面,由于 scan
操作是一个承诺(据我所知),如果我尝试 return 来自我自己的方法的承诺,该操作不会收到结果。
我很困惑,我真的很想了解如何让它发挥作用。
动作:
function getDynamodbTableRecords(tableName) {
return dispatch => {
dispatch(request());
var recordsSet = [];
var data = myAwsService.getTableRecords(tableName, null) || {Items:[]};
if (data.Items.length > 0){
data.Items.map(record => {
recordsSet.push(record);
});
dispatch(success(recordsSet));
} else {
dispatch(failure("No Records Found!"));
}
};
function request() { return { type: DATA_LOADING, selectedTable: tableName } }
function success(tableRecords) { return { type: DATA_LOAD_SUCCESS, tableRecords } }
function failure(error) { return { type: DATA_LOAD_FAILED, errors: error } }
}
myAwsService:
function getTableRecords(tableName, lastEvaluatedKey = null) {
getRecordsBatch(tableName, lastEvaluatedKey)
.then(
data => {
if (data.LastEvaluatedKey) {
return getTableRecords(tableName, data.LastEvaluatedKey)
.then(
nextData => {
data.Items = data.Items.concat(nextData.Items);
}
)
}
return data;
}
)
}
function getRecordsBatch(tableName, lastEvaluatedKey = null) {
var awsDynamodb = new DynamoDB();
let params = { TableName: tableName };
if (lastEvaluatedKey) {
params['ExclusiveStartKey'] = lastEvaluatedKey;
}
return new Promise((resolve, reject) => {
awsDynamodb.scan(params, function(err, data) {
if (err) {
reject(err);
}
return resolve(data);
});
});
}
不确定你的递归承诺是否有效,但我会这样做:
function getTableRecords(
tableName,
lastEvaluatedKey = null,
result = { Items: [] }
) {
return getRecordsBatch(tableName, lastEvaluatedKey).then(
data => {
if (data.LastEvaluatedKey) {
return getTableRecords(
tableName,
data.LastEvaluatedKey,
{
...data,
Items: result.Items.concat(data.Items),
}
);
}
return {
...data,
Items: result.Items.concat(data.Items),
};
}
);
}
该操作还应分派 data.Items 而不是 getTabelRecords returns 的承诺,如果出现问题,您可能希望分派失败操作:
function getDynamodbTableRecords(tableName) {
return async dispatch => {
dispatch(request());
//you probably want the data, not a promise of data
try {
var data = await myAwsService.getTableRecords(
tableName,
null
);
if (data.Items.length > 0) {
//no reason to have the temporary recordSet variable
dispatch(success(data.Items.map(record => record)));
} else {
dispatch(failure('No Records Found!'));
}
} catch (e) {
dispatch(failure(e.message));
}
};
function request() {
return { type: DATA_LOADING, selectedTable: tableName };
}
function success(tableRecords) {
return { type: DATA_LOAD_SUCCESS, tableRecords };
}
function failure(error) {
return { type: DATA_LOAD_FAILED, errors: error };
}
}