博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
node.js Domain 時代のエラー処理のコーディングパターン
阅读量:6644 次
发布时间:2019-06-25

本文共 4061 字,大约阅读时间需要 13 分钟。

さんの記事 。

ナイスです! なんと素晴らしいタイミングでのブログでしょうか!
「」で さんのプレゼンで node-v0.7.8 から isaacs 版 Domain が導入されるという発表がありましたが、予定通り昨日 Domain 機能付きの node-v0.7.8 がリリースされました。
しかもDomain のドキュメント付きです。
ちょうど さんの記事の例は node.js の新機能 Domain を教科書通りに適応するとどうなるのか紹介するのにぴったりのお題なので
Node.js v0.8 の新機能 Domain の使い方
について書かせていただきます。

Node.jsの新機能 Domain を使う

まずドメインを利用してエラー処理するには

  • domain モジュールの require()
  • domain オブジェクトの生成
  • domain で受けるエラーリスナーの登録
  • domain とエラーハンドリングとの結び付け
    • eventEmitter の場合は Domain.add
    • 関数の場合は Domain.bind

といった段取りが必要です。

さんの記事にあるコードを、Domain 使ったらどのようなコーディングパターンが考えられるかいくつ例示してみたいと思います。。(注:動作には node-v0.7.8 以降が必要です。)
今回3つのパターンで考えました。

  • パターン1: コールバック関数にドメインを結びつけてエラーハンドリングを行う
  • パターン2: 関数呼び出し時にドメインを結びつけてエラーハンドリングを行う
  • パターン3: 関数定義時にドメインを結びつけてエラーハンドリングを行う

ではサンプルコードとともにドメインを使ったコーディングパターンを例示していきます。

パターン1: コールバック関数にドメインを結びつける方法

まずはエラーオブジェクトを含むコールバックでドメインとエラーを結びつける場合です。

// domain_sample1.jsvar domain = require('domain');var fs = require('fs');var d = domain.create();function countChars(filename, callback) {  // コールバックに直接ドメインをバインド  fs.readFile(filename, 'utf-8', d.bind(function(err, data) {    if (err) throw err;    callback(data.length);  }));}function main(args) {  countChars(args[0], function(length) {    console.log(length);  });}d.on('error', function(err) {  console.log(err.message);});main(process.argv.slice(2))
unixjp:~/tmp/github/node> ./node domain_sample1.js hogeENOENT, open 'hoge'

はい、きれいなコードになりましたね。

パターン2: 関数呼び出しに時にドメインを結びつける方法

関数を呼び出すときにバインドしたい場合は、

// domain_sample2.jsvar fs = require('fs');var domain = require('domain');var d = domain.create();function countChars(filename, callback) {  fs.readFile(filename, 'utf-8', function(err, data) {    if (err) throw err;    callback(data.length);  });}function main(args) {  // 関数を呼び出す時にドメインをバインドする。  (d.bind(countChars))(args[0], function(length) {    console.log(length);  });}d.on('error', function(err) {  console.log(err.message);});main(process.argv.slice(2));

な感じです。

パターン3: 関数定義にドメインを結びつける方法

関数定義直後にバインドするなら、

// domain_sample3.jsvar fs = require('fs');var domain = require('domain');var d = domain.create();function countChars(filename, callback) {  fs.readFile(filename, 'utf-8', function(err, data) {    if (err) throw err;    callback(data.length);  });}// 関数定義直後にドメインにバインドcountChars = d.bind(countChars);function main(args) {  countChars(args[0], function(length) {    console.log(length);  });}d.on('error', function(err) {  console.log(err.message);});main(process.argv.slice(2));

といったようになります。

まとめ

他には event.EventEmitter のエラーと結び付けたい場合は Domain.bind() ではなく Domain.add() すればドメイン内のエラー処理で扱えます。

このように Domain の機能を使うとこれまでと違った形でエラーハンドリングをする可能性が広がり、従来より可読性の高く・簡潔なコードが書けるようになるでしょう。

追記: Domain.intercept() を使う

さんからのコメントにあるよう domain.bind(cb, true) だと throw しなくてもエラーをひっかけてくれます。(呼ばれる関数の第一引数が Error インスタンスであることが条件ですけど) これをまとめて domain.intercept() という関数になってます。

ということで domain.intercept() を使うともっとすっきりに書けます。

// domain_sample4.jsvar domain = require('domain');var fs = require('fs');var d = domain.create();function countChars(filename, callback) {  fs.readFile(filename, 'utf-8', d.intercept(function(err, data) {    callback(data.length);  }));}function main(args) {  countChars(args[0], function(length) {    console.log(length);  });}d.on('error', function(err) {  console.log(err.message);});main(process.argv.slice(2));
unixjp:~/tmp/github/node> ./node domain_sample4.js hogeENOENT, open 'hoge'

ありがとうございます。 > さん。

追記の追記: Domain.run() を使う。

またまた さんから twitter 経由で Domain.run() の使い方を教えていただきました。(実はマニュアルには記載されていませんけど)→ さんからのコメントで public API としてドキュメント化されました。

これを使うと上記パターン2(関数呼び出しに時にドメインを結びつける方法)のコードで (d.bind(fn))(args) と書いていたところが d.run(function() {fn(args)} と書けて、もっとすっきりします。

// domain_sample5.jsvar fs = require('fs');var domain = require('domain');var d = domain.create();function countChars(filename, callback) {  fs.readFile(filename, 'utf-8', function(err, data) {    if (err) throw err;    callback(data.length);  });}function main(args) {  // 関数を呼び出す時にドメインをバインドする。  d.run(function() {    countChars(args[0], function(length) {      console.log(length);    });  });}d.on('error', function(err) {  console.log(err.message);});main(process.argv.slice(2));

转载地址:http://cievo.baihongyu.com/

你可能感兴趣的文章
在 iOS 平台实现Ping 和 traceroute
查看>>
小猿圈python学习-嵌套&匿名&高阶函数
查看>>
element-ui 版本升级对比
查看>>
js 整理
查看>>
OOM
查看>>
Java Socket基础(二)
查看>>
基于Squid3.0的反向代理加速实现
查看>>
我的友情链接
查看>>
Xamarin XAML语言教程Xamarin.Forms中改变活动指示器颜色
查看>>
Jenkins Master/Slave架构
查看>>
[每日短篇] 9 - 去外包公司工作好还是不好?
查看>>
我的友情链接
查看>>
设计模式之创建型模式—— 1.4 单例模式
查看>>
Keepalived无法绑定VIP故障排查经历
查看>>
Linux Shell 程序调试
查看>>
php安装
查看>>
PHP操作XML(三)——RSS
查看>>
Oracle Dimension
查看>>
Start Developing iOS Apps Today系列(一)
查看>>
Storm笔记整理(四):Storm核心概念与验证——并行度与流式分组
查看>>