我试图以递归方式调用AWS的SNS listEndpointsByPlatformApplication。如果还有更多要返回的内容,则会返回前100个端点,然后返回NextToken
中的令牌(详情:AWS SNS listEndpointsByPlatformApplication)。
以下是我尝试的内容:
var getEndpoints = function(platformARN, token) {
return new models.sequelize.Promise(function(resolve, reject) {
var params = {
PlatformApplicationArn: platformARNDev
};
if (token != null) {
params['NextToken'] = token;
}
sns.listEndpointsByPlatformApplication(params, function(err, data) {
if (err) {
return reject(err);
}
else {
endpoints = endpoints.concat(data.Endpoints); //save to global var
if ('NextToken' in data) {
//call recursively
return getEndpoints(platformARN, data.NextToken);
}
else {
console.log('trying to break out!');
return resolve(true);
}
}
});
});
}
我用以下方式调用它:
getEndpoints(platformARNDev, null)
.then(function(ret) {
console.log('HERE!');
}, function(err) {
console.log(err);
});
问题是:第一次调用发生,然后发生递归调用,我收到消息trying to break out!
,但HERE!
永远不会被调用。我认为我的承诺如何回归我有点不对劲。
感谢指针。
答案 0 :(得分:4)
问题是您尝试解决/拒绝部分完成的查询。这是一个完整的虚拟服务工作示例。我把数据包含在它自己的递归函数中,只有当我完全获取所有数据或偶然发现错误时才解析/拒绝:
// This is the mock of the service. It yields data and token if
// it has more data to show. Otherwise data and null as a token.
var dummyData = [0, 1, 2, 3, 4];
function dummyAsyncCall(token, callback) {
token = token || 0;
setTimeout(function() {
callback({
dummyDataPart: dummyData[token],
token: (typeof (dummyData[token]) == 'undefined') ? null : (token + 1)
});
});
}
// Here is how you would recursively call it with promises:
function getAllData() {
//data accumulator is sitting within the function so it doesn't pollute the global namespace.
var dataSoFar = [];
function recursiveCall(token, resolve, reject) {
dummyAsyncCall(token, function(data) {
if (data.error) {
reject(data.error);
}
if (!data.token) {
//You don't need to return the resolve/reject result.
resolve(dataSoFar);
} else {
dataSoFar = dataSoFar.concat(data.dummyDataPart);
recursiveCall(data.token, resolve, reject);
}
});
}
return new Promise(function(resolve, reject) {
// Note me passing resolve and reject into the recursive call.
// I like it this way but you can just store them within the closure for
// later use
recursiveCall(null, resolve, reject);
});
}
//Here is the call to the recursive service.
getAllData().then(function(data) {
console.log(data);
});
答案 1 :(得分:1)
那是因为您不需要返回解析/拒绝,只需在递归调用完成时调用resolve / reject。粗略的代码看起来像这样
var getEndpoints = function(platformARN, token) {
return new models.sequelize.Promise(function(resolve, reject) {
var params = {
PlatformApplicationArn: platformARNDev
};
if (token != null) {
params['NextToken'] = token;
}
sns.listEndpointsByPlatformApplication(params, function(err, data) {
if (err) {
reject(err);
}
else {
endpoints = endpoints.concat(data.Endpoints); //save to global var
if ('NextToken' in data) {
//call recursively
getEndpoints(platformARN, data.NextToken).then(function () {
resolve(true);
}).catch(function (err) {
reject(err);
});
}
else {
console.log('trying to break out!');
resolve(true);
}
}
});
});
}
(警告:这只是一个粗略的代码,可能有用或可能没有,但是要提出一般性的想法)
我在下面添加了一个代码片段,以支持这个概念,并且效果很好,请查看。
i = 0;
$('#output').empty();
function pro() {
return new Promise(function(resolve, reject) {
if (i > 3) {
resolve();
return;
}
window.setTimeout(function() {
console.log(i);
$('#output').append(i).append('<br/>');
i += 1;
pro().then(function() {
resolve()
}).catch(function() {
reject()
});
}, 2000);
});
}
pro().then(function () { $('#output').append("now here"); })
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="output"></div>