Как заставить суперагент вернуть обещание

Я изучал Node/Javascript, используя промисы с самого начала (я не знаю, как не использовать промисы, и часто удивляюсь, как другие обходятся без них).

Поэтому мне иногда нужно «обещать» простые вещи, такие как чтение файла с fs:

var readFile = function(path) {
    return new Promise(function(fulfill, reject) {
        fs.readFile(path, function(err, data) {
            if (err) { reject(err); }
            else { fulfill(data); }
        });
    });
};

И это отлично работает. Теперь мне нужно сделать то же самое с superagent, но стиль цепочки, который он использует, меня застрял.

var request = require('superagent');
request.get(...).set(...).set(...).end(callback);  // stuck!

Я хотел бы заменить метод end() (или проигнорировать его и добавить новый метод) на тот, который возвращает обещание. Что-то вроде этого...

var endQ = function() {
    return new Promise(function(fulfill, reject) {
        this.end(function(err, res) {     // "this" is the problem!
            if (err) { reject(err); }
            else { fulfill(res); }
        });
    });
};

// then I could say this:
request.get(...).set(...).set(...).endQ().then(function(res) {
    // happiness
}).catch(function(err) {
    // sad about the error, but so happy about the promise!
});

В этом вопросе есть всевозможные советы по добавлению методов к объектам, но сложно посмотреть, что является окончательным. Меня особенно беспокоил этот ответ. Большая часть советов сосредоточена на том, чтобы начать с «класса» объекта и добавить функцию к .prototype. Что-то вроде этого....

// this part doesn't make sense
var requestInstance = new Request();   // no such thing in request as far as I know
requestInstance.prototype.endQ = endQ; // would be great, but no

Видишь мою проблему? Мне нужен JS-эквивалент «подкласса» запроса «класс» и добавления метода, но, поскольку это модуль, мне нужно рассматривать класс запроса как более или менее непрозрачный.


person user1272965    schedule 30.03.2016    source источник
comment
npmjs.com/package/superagent-as-promised   -  person Daniel Lizik    schedule 30.03.2016
comment
спасибо @Daniel_L, проверю. Просто ради удовольствия, то, что я пытаюсь решить в вопросе, выполнимо?   -  person user1272965    schedule 30.03.2016
comment
stackoverflow.com/questions/29595449/   -  person Daniel Lizik    schedule 30.03.2016


Ответы (1)


Во-первых, суперагент уже поддерживает промисы :

request.get(...).set(...).set(...).then(response => {
    // handle it here
});

Обратите внимание, что в отличие от обычного then, then здесь не является обещанием, а фактически вызывает запрос и действует лениво.

Во-вторых, то, что вы хотите сделать, довольно просто:

Object.getPrototypeOf(request.get(...)).endQ = function() { // get to prototype and define
  /* your code here */
};

Вот что делает сам суперагент:

exports.then = function then(resolve, reject) {
  if (!this._fullfilledPromise) {
    var self = this;
    this._fullfilledPromise = new Promise(function(innerResolve, innerReject){
      self.end(function(err, res){
        if (err) innerReject(err); else innerResolve(res);
      });
    });
  }
  return this._fullfilledPromise.then(resolve, reject);
}
person Benjamin Gruenbaum    schedule 31.03.2016
comment
Спасибо большое. Я собираюсь использовать нативное обещание, которое вы предлагаете, но меня немного смущает getPrototypeOf(request.get(...)). Разве это не getPrototypeOf(request) ? В противном случае, разве я не получил бы прототип результата вызова get? Еще раз спасибо всем за помощь. - person user1272965; 03.04.2016