【问题标题】:How to write a setup for an NPM package如何为 NPM 包编写设置
【发布时间】:2016-06-12 02:44:17
【问题描述】:

我正在编写我的第一个 node.js 包以帮助使 REST API 更易于使用,但我在格式化包以允许使用该包的人在其应用程序中执行以下操作时遇到问题。

var Water= require("water-reservation");

var water = Water({username: myusername, password: mypassword});

// Problem here because Water({}) needs to do a REST call to get a bearer 
// token to use the API I am trying to simplify. Thus, it tries to 
// get_water(callabck) before the bearer_token var is set in my package.

water.get_water(function(err, result){
    if(err){
        console.log(err);
        console.log("----------------------------------------------");
    }
    else{
        console.log(result);
        console.log("----------------------------------------------");
    }
});

在我当前的设置中,我获取用户的用户名和密码并将其传递到 REST 端点以获取我在所有 REST 调用中使用的不记名令牌。在我完成在我的包中设置 Bearer_token 变量之前,异步性质将在用户文件中调用 get_water。

这是我的包裹的样子:

var request = require('request');
var bearer_token = "";
var api_url = "";

var Water = function(credentials){
    api_url = credentials.api_url;
    var username = credentials.username;
    var password = credentials.password;

    get_bearer_token(username, password, function(err, access_token){
      bearer_token = access_token;
    });
};

function get_bearer_token(username, password, callback){
    var request_options = {
        url: api_url + "/auth",
        method: "GET",
        'auth': {
            'user': username,
            'pass': password
        }
    };

    request(request_options, function(err, res, body){
        if(err) {
            return callback("Water Initialization Error: " + err, null);
        }
        else {
            return callback(null, body);
        }
    });
}

// Get water
Water.prototype.get_water = function(callback) {
    var request_options = {
        url: api_url + "/water",
        method: "GET",
        'auth': {
            'bearer': bearer_token
        }
    };

    request(request_options, function(err, res, body){
        if(err) {
            return callback(err, null);
        }
        else{
            return callback(null, body);
        }
    });
};

// more package functions...

module.exports = Water;

我正在尝试找到一种方法来进行设置,以便用户可以使用上述软件包。我不喜欢那种风格,但它似乎是用户最容易理解和使用的风格。

我能想到的解决此问题的唯一方法是向 Water({}) 添加回调,但如果用户将所有与水相关的代码都包含在回调中,这会造成很多混乱。我知道这可以通过查看 Twitter 包来完成,但我仍然可以思考他们是如何做到的。任何帮助将不胜感激,谢谢。

【问题讨论】:

  • node-twitter 包似乎没有在原型函数中发出任何异步请求。
  • 也许我应该让用户提供他们的不记名令牌,而不是在设置中执行休息请求。虽然,我更愿意通过为他们获取令牌来帮助他们更容易使用包。

标签: node.js npm package


【解决方案1】:

您应该将获取令牌的责任委托给他们提出请求时。这样包就会立即初始化。为了提高效率,您可以在第一次获取令牌时对其进行缓存。我在这里做了一个例子,但你可以使用 async 之类的东西来整理它:

var request = require('request');

var Water = function (credentials) {
    this.api_url = credentials.api_url;
    this.username = credentials.username;
    this.password = credentials.password;

    return this;
};

Water.prototype.get_bearer_token = function (callback) {
    // We already have the bearer token, so return straight away
    if (this.bearer_token) return callback(null, this.bearer_token);

    var self = this;
    var request_options = {
        url: this.api_url + "/auth",
        method: "GET",
        'auth': {
            'user': this.username,
            'pass': this.password
        }
    };

    request(request_options, function(err, res, body){
        if(err) {
            return callback("Water Initialization Error: " + err, null);
        }
        else {
            self.bearer_token = body;
            return callback(null, body);
        }
    });
}

// Get water
Water.prototype.get_water = function(callback) {
    var self = this;
    this.get_bearer_token(function (err, token) {
        if (err) return callback(err);

        var request_options = {
            url: self.api_url + "/water",
            method: "GET",
            'auth': {
                'bearer': token
            }
        };

        request(request_options, function(err, res, body){
            if(err) {
                return callback(err, null);
            }
            else{
                return callback(null, body);
            }
        });
    });

};

// more package functions..
module.exports = Water;

使用它:

var Water = require('water-reservation');

var water = new Water({
  username: 'username',
  password: 'pass',
  api_url: 'http://example.com'
});

water.get_water(function (err, res) {

});

【讨论】:

  • 酷,感谢您的解决方案和示例!因此,对于我使用此包创建的每个函数,我都应该包含一个用于获取令牌 this.get_bearer_token(function (err, token) {};) 的回调,我想知道是否有办法避免在包的每个方法中重复相同的回调,以提高可读性并减少冗余。
  • 为了避免嵌套回调,您可以使用异步瀑布(或承诺)将其展平。但是,如果只是获取承载令牌然后发出请求,我可能不会打扰。
猜你喜欢
  • 2016-08-22
  • 2013-01-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-19
相关资源
最近更新 更多