簡體   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