2016-06-11 4 views
2

Я пишу свой первый пакет node.js, чтобы упростить использование REST API, и у меня возникли проблемы с форматированием пакета, чтобы позволить человеку, использующему пакет, сделать ниже их применения.Как написать установку для пакета NPM

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 требует пакета. Асинхронный характер вызовет get_water в файле пользователя, прежде чем я закончу настройку переменной bearer_token в моем пакете.

Вот что мой пакет выглядит следующим образом:

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; 

Я пытаюсь найти способ, чтобы сделать установку, так что пользователь может использовать пакет, как описано выше. Я не настроен на этот стиль, но, по-видимому, он проще всего понять и использовать.

Единственный способ, которым я мог подумать об исправлении этого вопроса, - это добавить обратный вызов для воды ({}), но это сделало бы большой беспорядок, когда пользователь обернул бы весь свой связанный с водой код в обратном вызове. Я знаю, что это можно сделать, если посмотреть на пакет Twitter, например, но я все равно могу обдумать, как они это сделали. Любая помощь будет оценена, спасибо.

+0

Нода '-twitter' пакет, кажется, не делать какие-либо асинхронные запросы в функции прототипа. – gnerkus

+1

Возможно, я должен предоставить пользователю свой токен-носитель и не выполнять запрос на отдых в настройке. Хотя, я бы предпочел быть полезным, получив для них токен, чтобы упростить использование пакета. –

ответ

1

Вы должны делегировать ответственность за получение маркера, когда они делают запрос. Таким образом, пакет инициализируется мгновенно. Чтобы сделать его более эффективным, вы можете кэшировать токен в первый раз, когда он будет извлечен. Я привел пример здесь, но вы могли бы привести в порядок его использовать что-то вроде асинхронном:

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

}); 
+0

круто, спасибо за решение и пример! Поэтому для каждой функции, которую я делаю с этим пакетом, я должен включить обратный вызов для получения токена 'this.get_bearer_token (function (err, token) {};)' Интересно, есть ли способ избежать повторения того же обратного вызова в каждом методе пакета для повышения удобочитаемости и сокращения избыточности. –

+0

Чтобы избежать вложенного обратного вызова, вы можете использовать async waterfall (или обещания), чтобы сгладить его. Однако, если это просто получить токен-носитель, а затем сделать запрос, я, вероятно, не беспокоюсь. – MrWillihog

Смежные вопросы