"调用堆栈"用于node.js中的回调

Ren*_*ett 6 javascript asynchronous stack-trace control-flow node.js

我习惯用Java思考,而我正试图绕过node.js. 我的程序需要在出现问题时记录信息,我发现我必须在我的node.js程序中输入大量的样板代码才能获得我在Java中免费获得的内容.

我的问题归结为:

  • 是否有一种更简单/非样板的方法来获得回调链中的类似堆栈的信息?和/或
  • 我是否未能正确掌握node.js,并试图强制异步node.js更像是同步Java?

Java示例

这是一个点头的Java程序,它尝试(并且失败)连接到Mongo数据库: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");
    }

}
Run Code Online (Sandbox Code Playgroud)

...这给出了有用的堆栈输出:

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)
Run Code Online (Sandbox Code Playgroud)

(特别是,在发生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);
    });
}
Run Code Online (Sandbox Code Playgroud)

...给出了这个输出:

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]]
Run Code Online (Sandbox Code Playgroud)

但是为了得到这个输出,我必须在我的程序中加入大量样板代码,这对于警察来说将是一种痛苦,因为我的程序越来越大,我有一个完整的开发团队.

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

Esa*_*ija 3

Promise 正是您正在寻找的(将堆栈功能带回异步代码)

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) {

});
Run Code Online (Sandbox Code Playgroud)

给出:

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
Run Code Online (Sandbox Code Playgroud)

您可以在一处使用 catch(如此命名是因为它的工作方式类似于真正的 catch 语句):

 a().catch(function(e) {
      //handle e
 });
Run Code Online (Sandbox Code Playgroud)

还添加了蓝鸟特定功能来捕捉:

还支持谓词捕获,因为它只是一种方法:

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

 });
Run Code Online (Sandbox Code Playgroud)

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

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