繁体   English   中英

蓝鸟Javascript承诺:处理指定的错误后停止执行

[英]Bluebird Javascript Promise: stop execution after dealing with specified error

我有一个稍微复杂的流程,该entryUrl从数据库接收一个entryUrl ,检查它重定向到的位置,然后使用exitUrl更新它。

基本上,流程应如下所示:

  • 检索Url没有离开网址
    • 使用request获取Url.entryUrl的标头
      • 如果有意外的响应或重置了连接,请标记此Url并继续下一个
    • 解析由执行的request产生的exitUrl
      • 存储exitUrl
      • 继续下一个Url
  • 如果没有可用的Url请在5秒钟后重试
  • 如果上述链或子链中出现任何意外错误,请在60秒后重试

我当前的实现是这样的,使用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';
}

现在的问题是,如果存在ConnResetErrorResponseError ,则catch块将按应有的方式执行,但是spread调用then块也将被执行-但我希望在捕获到这些内容之后做一些事情后停止执行2种特定的错误类型。

我将如何实现这种执行流程?

就像在同步代码-如果你有一个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
});

从内部的诺言中,当您第一次catch ResponseError或ConnResetError时,您通常会返回(即不抛出),因此后续的诺言链成功,执行了then()spread()分支,而不是失败并转到catch()分支机构。

您可能希望像这样重写内部的诺言catch块:

...
.catch(ResponseError, function(err) {
     log.error('got strange response');
     throw err;
})
...

基本上,重新抛出Error ,如果你想继续把它当作一个错误:你抓了。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM