2016-10-21 6 views
2

Node.jsでは、ファイルを読み込んでその内容をすべて非同期で検証する必要があります。私はのNode.js 6.6ブルーバード3.4.6複数のキャッチで約束を止める

例コードを使用してM:

// pseudo function to read file contents - resolves when 'flag' is true, rejects when 'flag' is false. 
 
function readFile(flag) { 
 
    return new Promise(function (resolve, reject) { 
 
     console.log('Reading file...'); 
 
     if (flag) { 
 
      resolve('File contents'); 
 
     } else { 
 
      reject('readFile error'); 
 
     } 
 
    }); 
 
} 
 

 
// pseudo function to validate file contents - resolves when 'flag' is true, rejects when 'flag' is false. 
 
function validate(fileContents, flag) { 
 
    return new Promise(function (resolve, reject) { 
 
     console.log('Validating file: ', fileContents); 
 
     if (flag) { 
 
      resolve('Validate passed'); 
 
     } else { 
 
      reject('validation failed'); 
 
     } 
 
    }); 
 
} 
 

 

 
readFile(false) 
 
    .then(function (fileContents) { 
 
     console.log('Successfully read the file:', fileContents); 
 
     return fileContents; 
 
    }) 
 
    .catch(function (fileReadErr) { 
 
     console.log('Failed to read the file:', fileReadErr); 
 
     throw fileReadErr; // or, return Promise.reject(err); 
 
    }) 
 
    .then(function (fileContents) { 
 
     return validate(fileContents, false); 
 
    }) 
 
    .then(function (result) { 
 
     console.log('Successfully validated the file:', result); 
 
    }) 
 
    .catch(function (err) { 
 
     console.log('Failed to validate the file:', err); 
 
    }) 
 
    ;
<script src="https://cdn.jsdelivr.net/bluebird/3.4.6/bluebird.min.js"></script>

は、上記のコードが印刷され

Reading file... 
Failed to read the file: readFile error 
Failed to validate the file: readFile error 

上記に約束チェーンはおおよそ以下の同期コードに変換されます:

try { 
    let fileContents; 

    try { 
     fileContents = readFile(false); 
     console.log('Successfully read the file:', fileContents); 
    } catch (e) { 
     console.log('Failed to read the file:', e); 
     throw e; 
    } 

    let validationResult = validate(fileContents, false); 
    console.log('Successfully validated the file:', validationResult); 
} catch (err) { 
    console.log('Failed to validate the file:', err); 
} 

そして、まだ第二catch方法を呼び出します最初catchの方法で投げるか、拒否します。

私の質問:ファイルの読み込みが失敗したらチェーンを破る方法はありますか?私の目的は、express.jsルートからさまざまなHTTPステータスコード(ファイル読み込みエラー:500、検証失敗:400)を返すことです。

私は非標準の特殊化されたcatchメソッドを使用して解決策を知っていますが、特別な処理が必要です。その意味で、私はエラーを投げたり、エラーオブジェクトに何らかのフィルタリングキーを必要とし、どちらも私の手にはないし、それを達成するための仕事が必要です。このソリューションは、ここで青い鳥ドキュメント&に記載されている:Handling multiple catches in promise chain

+0

これをhttp://stackoverflow.com/questions/26076511/handling-multiple-catches-in-promise-chainの複製としたい方には、他の可能な解決策を知りたい@Esailija(青い鳥の作者)がここで述べた連鎖の終わりにある「キャッチ」のすべてのエラーを処理したくないのです。http://stackoverflow.com/a/26077569/340290 – manikanta

+0

あなたの質問は、答えはおそらく "いいえ、キャッチチェーンを破る方法はありません"です。チェーンの終わりに最終的なキャッチハンドラを使用することに異論はありますか? – CodingIntrigue

+0

最後に 'catch'を使用するには、少なくともフラグを維持するか、エラーオブジェクトを確認してさまざまなエラー状態を知る必要があります。それはif-elseif-elseとなるでしょう。ではない? – manikanta

答えて

1

あなたがそうのようなカスタムエラーの種類を作成することができます。

ReadFileError = function() {}; 
ReadFileError.prototype = Error.prototype; 

ValidationError = function() {}; 
ValidationError.prototype = Error.prototype; 

次に、あなたが代わりに拒否の約束からthrowことができます。

function validate(fileContents, flag) { 
    return new Promise(function (resolve, reject) { 
     console.log('Validating file: ', fileContents); 
     if (flag) { 
      resolve('Validate passed'); 
     } else { 
      throw new ReadFileError('readFile error'); 
     } 
    }); 
} 

次に、タイプに基づいてさまざまなエラーを検出できます。

readFile(false) 
    .then(function (fileContents) { 
     console.log('Successfully read the file:', fileContents); 
     return fileContents; 
    }) 
    .then(function (fileContents) { 
     return validate(fileContents, false); 
    }) 
    .then(function (result) { 
     console.log('Successfully validated the file:', result); 
    }) 
    .catch(ReadFileError, function (err) { 
     console.log(..., err); 
    }) 
    .catch(ValidationError, function (err) { 
     console.log(..., err); 
    }) 
    catch(function(err) { 
     ... 
    }); 
+0

答えをありがとう。しかし、私はこの解決策を知っていたと私は言いましたように、別の例外を手にすることはありません。私は 'bluebird.promisifyAll'メソッドを使ってfs'、' mysql'メソッドをPromiseでラップしています。これらのメソッドは、単にコールバック呼び出しに基づいて解決または拒否されます。 – manikanta

3

私が「断熱された漁場」と呼ぶものを使うのが最も簡単な解決策です。すなわち、各プロセスが全体的に特定のステップに関連付けられており、メインチェーンは.thensのみ(および最終的に単一のターミナルキャッチ)で構成されているパターンです。

また、この種の状況では、追加された情報を追加したプロパティを持つErrorオブジェクトを再スローすることによって、エラーパスの下で追加情報を伝えることが有用です。これにより、カスタムエラーの必要性が回避されます。

Promise.resolve() 
.then(function() { 
    return readFile(false) 
    .then(function (fileContents) { 
     console.log('Successfully read the file:', fileContents); 
     return fileContents; 
    }) 
    .catch(function (error) { 
     error.code = 521; // or whatever 
     error.customMessage = 'Failed to read the file'; 
     throw error; 
    }) 
}) 
.then(function (fileContents) { 
    return validate(fileContents, false) 
    .then(function (result) { 
     console.log('Successfully validated the file:', result); 
     return fileContents; 
    }) 
    .catch(function (error) { 
     error.code = 522; // or whatever 
     error.customMessage = 'Failed to validate the file'; 
     throw error; 
    }); 
}) 
.catch(function(error) { // terminal catch. 
    console.log(error); 
    // It's possible for unaugmented errors to reach this point, 
    // so be sure to test for the extra properties before trying to use them. 
    if(error.code) {...} 
    if(error.customMessage) {...} 
    // Note also that the original error.message is still intact. 
}); 

初期Promise.resolve()は厳密には必要ではないが、対称的、他のすべてを保つことができます。

これは、Promises/A + libで動作します。ブルーバード・シュガーは必要ありません。

0

あなたが達成したいことを理解する限り、私はいつも1つのキャッチブロックを使用することを提案します(いくつかのユースケースで完全にOKですが、あなたが潜在的にすべての周りインデントと約束地獄)

はあなたの関数のような統一的な方法でreadFilevalidateにすべてのエラーを処理することができてしまいますので、:そして、

const error = new Error('something bad happened') 
error.status = 500 
return reject(error) 

あなたがエラーロジックを処理行うことができますに基づく単一のキャッチブロック内210などres.status(err.status || 500).json(...)

関連する問題