调用node.js中的callback函数

我习惯于在Java中思考,我试图让我的头绕过node.js。 当程序出错时,我的程序需要logging信息,而且我发现我不得不在node.js程序中join很多样板代码,以便在Java中免费获得。

我的问题归结为:

  • 有没有一种更简单/非模板化的方式来获取一系列callback中的类似堆栈的信息? 和/或
  • 我是否无法正确掌握node.js,并试图强制asynchronousnode.js更像是同步Java?

Java示例

这是一个尝试(并失败)连接到Mongo数据库的noddy Java程序:import java.net.UnknownHostException;

import com.mongodb.Mongo; public class Test { public static void main(final String[] args) throws UnknownHostException { final Mongo mongo = a(); } private static Mongo a() throws UnknownHostException { return b(); } private static Mongo b() throws UnknownHostException { return c(); } private static Mongo c() throws UnknownHostException { return new Mongo("non-existent host"); } } 

…这给了这个有用的堆栈输出:

 Exception in thread "main" java.net.UnknownHostException: non-existent host at java.net.Inet6AddressImpl.lookupAllHostAddr(Native Method) at java.net.InetAddress$1.lookupAllHostAddr(Unknown Source) at java.net.InetAddress.getAddressesFromNameService(Unknown Source) at java.net.InetAddress.getAllByName0(Unknown Source) at java.net.InetAddress.getAllByName(Unknown Source) at java.net.InetAddress.getAllByName(Unknown Source) at java.net.InetAddress.getByName(Unknown Source) at com.mongodb.ServerAddress.updateInetAddress(ServerAddress.java:204) at com.mongodb.ServerAddress.<init>(ServerAddress.java:73) at com.mongodb.ServerAddress.<init>(ServerAddress.java:46) at com.mongodb.Mongo.<init>(Mongo.java:138) at Test.c(Test.java:20) at Test.b(Test.java:16) at Test.a(Test.java:12) at Test.main(Test.java:8) 

(特别是,在Mongo错误发生时,最后4行显示了我自己的代码中发生了什么)。

Node.js示例

以下是我尝试在node.js中重写我的程序:

 a(function (err, mongo) { if (err) { console.log("Something went wrong in main"); console.log(err); } }); function a(callback) { b(function (err, mongo) { if (err) { console.log("Something went wrong in a()"); return callback(err); } return callback(null, mongo); }); } function b(callback) { c(function (err, mongo) { if (err) { console.log("Something went wrong in b()"); return callback(err); } return callback(null, mongo); }); } function c(callback) { var MongoClient = require('mongodb').MongoClient; return MongoClient.connect('mongodb://non-existent host/', function (err, mongo) { if (err) { console.log("Something went wrong in c()"); return callback(err); } return callback(null, mongo); }); } 

…给出这个输出:

 Something went wrong in c() Something went wrong in b() Something went wrong in a() Something went wrong in main [Error: failed to connect to [non-existent host:27017]] 

但是为了得到这个输出结果,我必须在整个程序中join大量的样板代码,随着程序越来越大,我将有一个完整的开发团队,这对于警察来说是一个痛苦。

我能否以另一种方式获得这种类似堆栈的输出? 期望这种输出是否像节点一样?

承诺正是你正在寻找(带回堆栈functionasynchronous代码)

 var Promise = require("bluebird"); var mongodb = require("mongodb"); // enable long stack traces, bluebird specific Promise.longStackTraces(); // promisify mongodb so that it returns promises, also bluebird specific Promise.promisifyAll(mongodb); // raise stack limit, feature of v8/node.js Error.stackTraceLimit = 100; function c() { var MongoClient = require("mongodb").MongoClient; return MongoClient.connectAsync('mongodb://non-existent host/') } function b() { return c() } function a() { return b() } a().then(function(connection) { }); 

得到:

 Possibly unhandled Error: failed to connect to [non-existent host:27017] at null.<anonymous> (/home/petka/bluebird/node_modules/mongodb/lib/mongodb/connection/server.js:546:74) at EventEmitter.emit (events.js:106:17) at null.<anonymous> (/home/petka/bluebird/node_modules/mongodb/lib/mongodb/connection/connection_pool.js:150:15) at EventEmitter.emit (events.js:98:17) at Socket.<anonymous> (/home/petka/bluebird/node_modules/mongodb/lib/mongodb/connection/connection.js:533:10) at Socket.EventEmitter.emit (events.js:95:17) at net.js:830:16 From previous event: at Function.connectAsync (eval at makeNodePromisifiedEval (/home/petka/bluebird/js/main/promisify.js:199:12), <anonymous>:7:21) at c (/home/petka/bluebird/throwaway.js:10:28) at b (/home/petka/bluebird/throwaway.js:14:16) at a (/home/petka/bluebird/throwaway.js:18:16) at Object.<anonymous> (/home/petka/bluebird/throwaway.js:21:5) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:902:3 

你可以在一个地方使用catch(因为它像一个真正的catch语句那样命名):

  a().catch(function(e) { //handle e }); 

此外蓝鸟特定的function添加到赶上:

由于这只是一种方法,所以也支持预测捕获量:

  a().catch(SyntaxError, function(e) { }); 

谓词可以是错误构造函数或谓词函数

  // define a predicate for IO errors function IOError(e) { return "code" in Object(e); } 

如何使用堆栈跟踪从错误:

 function trace(err) { console.log(err); var stack = new Error().stack; console.log(stack); } a(function (err, mongo) { if (err) trace(err) }); function a(callback) { b(function (err, mongo) { if (err) return callback(err); else return callback(null, mongo); }); } function b(callback) { c(function (err, mongo) { if (err) return callback(err); else return callback(null, mongo); }); } function c(callback) { var MongoClient = require('mongodb').MongoClient; return MongoClient.connect('mongodb://nohost/', function (err, mongo) { if (err) return callback(err); else return callback(null, mongo); }); } 

产量

 [Error: failed to connect to [non-existent host:27017]] Error at trace (/myfolder/a.js:4:14) at /myfolder/a.js:11:2 at /myfolder/a.js:17:10 at /myfolder/a.js:26:10 at /myfolder/a.js:36:10 at /myfolder/node_modules/mongodb/lib/mongodb/mongo_client.js:406:11 at process._tickCallback (node.js:339:11) 

现在它不像Java中那样冗长,它不给函数名称,但它有助于识别执行链。

longjohn现在似乎很受欢迎,因为在node.js中有很长的堆栈跟踪

http://blog.nodejitsu.com/npmawesome-full-stack-traces-with-longjohn/

http://www.mattinsler.com/post/26396305882/announcing-longjohn-long-stack-traces-for-node-js

这里是其他这样的模块列表,可能有助于确定你需要什么

https://nodejsmodules.org/tags/stack

示例代码:

 var longjohn = require('longjohn') var stackTrace = require('stack-trace'); longjohn.empty_frame = 'ASYNC CALLBACKS :'; a(); function a() { b(); }; function b() { c(); } function c() { setTimeout(function() { throw new Error("My Custom Error"); }, 1000); } process.on('uncaughtException', function(err) { //in JSON format with the help of stack-trace module; console.error(stackTrace.parse(err)); //in plain text format console.error(err.stack.trim()); process.exit(1); }); 

以longjohn输出纯文本格式:

 Error: My Custom Error at [object Object].<anonymous> (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:19:9) at listOnTimeout (timers.js:110:15) ASYNC CALLBACKS : at c (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:17:2) at b (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:12:2) at a (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:8:2) at Object.<anonymous> (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:4:1) at Module._compile (module.js:456:26) at Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Module._load (module.js:312:12) 

以不带longjohn的纯文本格式输出:

 Error: My Custom Error at null._onTimeout (/Users/nav/Documents/workspace/stack_trace/hello-world-server.njs:19:9) at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)