我有一个有点复杂的流程,从数据库接收entryUrl
,检查重定向到的位置,然后用exitUrl
更新它。
基本上流程应该是这样的:
Url
Url.entryUrl
获取request
标头
Url
并继续下一个exitUrl
执行的request
exitUrl
Url
Url
可用,请在5秒后重试我当前的实现是这样的,使用Bluebird javascript promise样式:
function processNext() {
return api.getUrlWithoutExitUrl()
.then(function followEntryUrl(url)
{
if (!url || !url.entryUrl)
{
throw new NoUrlAvailableError();
}
log.info('getting exit url for ' + url.entryUrl);
return [
request({
method : 'HEAD',
url : url.entryUrl,
followAllRedirects : true,
maxRedirects : 20
})
.catch(ResponseError, function()
{
log.error('got strange response');
})
.catch(ConnResetError, function()
{
log.error('connection was reset');
})
.then(function removeInvalidUrl()
{
log.info('remove invalid url'); //FIXME: after doing this, we should not continue with the other `then` calls
}),
url
];
})
.spread(function parseExitUrl(res, url)
{
if (!res[0] || !res[0].request || !res[0].request.uri || !res[0].request.uri.href)
{
throw new InvalidUrlError();
}
return [res[0].request.uri, url];
})
.spread(function storeExitUrl(parsedExitUrl, url)
{
return api.setUrlExitUrl(url, parsedExitUrl);
})
.then(processNext)
.catch(InvalidUrlError, function()
{
log.info('an attempted url is invalid, should set as processed and continue with next immediately');
})
.then(processNext)
.catch(NoUrlAvailableError, function()
{
log.info('no url available, try again after a while');
})
.delay(5000)
.then(processNext)
.catch(function(err)
{
log.error('unexpected error, try again after a long while');
log.error(err);
log.error(err.constructor);
})
.delay(60000)
.then(processNext);
}
processNext();
function ResponseError(e)
{
return e && e.code === 'HPE_INVALID_CONSTANT';
}
function ConnResetError(e)
{
return e && e.errno === 'ECONNRESET';
}
现在问题是,如果有ConnResetError
或ResponseError
,则会按原样执行catch块,但then
块会跟随spread
1}}调用也被执行 - 但我希望执行在捕获这两种特定错误类型之后完成某些操作后停止。
我如何实现这样的执行流程?
答案 0 :(得分:0)
就像在同步代码中一样 - 如果你有catch
要执行某些处理然后传播错误 - 你可以重新抛出它:
同步代码:
try {
a = makeRequest();
} catch(e) {
// handle
throw e;
}
承诺:
makeRequest().catch(e => {
// handle
throw e; // also a good idea to add data to the error here
});
答案 1 :(得分:0)
从您的内心承诺,当您第一次catch
ResponseError或ConnResetError时,您正常返回(即不投掷),因此后续的承诺链成功,执行其then()
和spread()
分支,而不是失败并前往catch()
分支。
您可能想要重写内部承诺catch
块,如下所示:
...
.catch(ResponseError, function(err) {
log.error('got strange response');
throw err;
})
...
基本上,如果您想继续将其视为错误,请重新抛出您抓到的Error
。