Bluebird promisifyAll не создает полный набор асинхронных функций

Может быть, я не понимаю, как работает Promise.promisifyAll. Я пытаюсь обещать пакет coinbase.

По сути, клиентские функции обещаны, но аккаунты, возвращаемые этими функциями, не имеют асинхронной версии: [TypeError: acc.getTransactionsAsync is not a function].

Я попытался передать {multiArgs:true} в качестве параметров Promise.promisifyAll(), как это было предложено в ответе на аналогичный вопрос, но это не решило проблему. Любое предложение приветствуется.

Обычный способ использования пакета (работает):

var Client = require('coinbase').Client

var client = new Client({
  'apiKey': '<snip>',
  'apiSecret': '<snip>',
  'baseApiUri': 'https://api.sandbox.coinbase.com/v2/',
  'tokenUri': 'https://api.sandbox.coinbase.com/oauth/token'
});

//Callbacks
client.getAccounts({}, function(err, accounts) {
  accounts.forEach(function(acc) {
    acc.getTransactions(null, function(err, txns) {
      txns.forEach(function(txn) {
        console.log('txn: ' + txn.id);
      });
    });
  });
});

Обещанная версия не работает (getTransactionsAsync не определено, но getAccountsAsync корректно возвращает аккаунты):

var Promise = require('bluebird');
var Client = require('coinbase').Client;

var client = new Client({
  'apiKey': '<snip>',
  'apiSecret': '<snip>',
  'baseApiUri': 'https://api.sandbox.coinbase.com/v2/',
  'tokenUri': 'https://api.sandbox.coinbase.com/oauth/token'
});

Promise.promisifyAll(client);

//Promises
client.getAccountsAsync({}) //Works perfectly, returns the accounts
.then(function(accounts) {
  return Promise.map(accounts, function(acc) {
    return acc.getTransactionsAsync(null); //This function call is throwing the TypeError
  });
})
.then(function(transactions) {
  console.log('Transactions:');
  transactions.forEach(function(tx) {
    console.log(tx);
  });
})
.catch(function(err) {
  console.log(err);
});

ИЗМЕНИТЬ:

Просматривая пакет, который я хочу обещать, я понял, что функции, которые я пытаюсь вызвать, взяты из объектов модели, возвращаемых пакетом. Думаю promisifyAll только парсит клиентские функции, а модели не обрабатываются. Я просто не очень хорошо разбираюсь в том, как делается парсинг :(

Это index.js (модуль экспортирован)

var Account       = require('./lib/model/Account.js'),
    Address       = require('./lib/model/Address.js'),
    Buy           = require('./lib/model/Buy.js'),
    Checkout      = require('./lib/model/Checkout.js'),
    Client        = require('./lib/Client.js'),
    Deposit       = require('./lib/model/Deposit.js'),
    Merchant      = require('./lib/model/Merchant.js'),
    Notification  = require('./lib/model/Notification.js'),
    Order         = require('./lib/model/Order.js'),
    PaymentMethod = require('./lib/model/PaymentMethod.js'),
    Sell          = require('./lib/model/Sell.js'),
    Transaction   = require('./lib/model/Transaction.js'),
    User          = require('./lib/model/User.js'),
    Withdrawal    = require('./lib/model/Withdrawal.js');

var model = {
  'Account'       : Account,
  'Address'       : Address,
  'Buy'           : Buy,
  'Checkout'      : Checkout,
  'Deposit'       : Deposit,
  'Merchant'      : Merchant,
  'Notification'  : Notification,
  'Order'         : Order,
  'PaymentMethod' : PaymentMethod,
  'Sell'          : Sell,
  'Transaction'   : Transaction,
  'User'          : User,
  'Withdrawal'    : Withdrawal
};

module.exports = {
  'Client' : Client,
  'model'  : model
};

РЕДАКТИРОВАТЬ 2:

Клиенту требуются свои собственные модули модели, поэтому Promise.promisifyAll должен, как и ожидалось, со свойствами объекта без вмешательства предыдущего редактирования. На данный момент я думаю, что не может быть другого варианта, кроме как создавать свои собственные промисы для всех функций, которые мне понадобятся, которые не находятся непосредственно под клиентом.


person Fdo    schedule 20.04.2016    source источник
comment
Я пытаюсь избежать создания большого количества new Promise(...) функций, но пока не могу найти другого способа решить эту проблему.   -  person Fdo    schedule 20.04.2016


Ответы (2)


Думаю promisifyAll только парсит клиентские функции, а модели не обрабатываются.

Не совсем. Это не имеет ничего общего с тем, как promisifyAll просматривает методы и свойства. Скорее, вы явно передаете только обещанные клиентские методы:

var Client = require('coinbase').Client;
var client = new Client(…);
Promise.promisifyAll(client);

Ссылки с client на модели нет. Попробуйте вызвать promisifyAll для всего модуля, а не только для класса Client:

var Client = Promise.promisifyAll(require('coinbase')).Client;

или, если это не сработает, вызовите promisifyAll как для класса Client, так и для набора классов models:

var coinbase = require('coinbase');
var Client = Promise.promisifyAll(coinbase.Client);
Promise.promisifyAll(coinbase.model);
person Bergi    schedule 20.04.2016
comment
Это тоже не сработало, это был оригинальный способ, которым я звонил. После ответа/предложения я изменил его на этот, но он удалил свой ответ, и я полагаю, что это он проголосовал за мой вопрос. Внутри клиента есть требования к моделям как к свойствам, поэтому они должны быть промисифицированы (но это не так), см. РЕДАКТИРОВАТЬ 2. Я не хотел копировать и вставлять еще один большой файл, вопрос уже слишком длинный. - person Fdo; 20.04.2016
comment
Нет, только потому, что для файла client.js требуются некоторые из файлов modules/…, это не означает, что они будут обещаны. Он будет обещать только те классы, которые доступны как свойства из Client или Client.prototype. - person Bergi; 20.04.2016
comment
Ах да, promisifyAll не собирается углубляться в coinbase.models, потому что это не класс (нет имени в верхнем регистре и т. д.). - person Bergi; 20.04.2016
comment
Углубляться в coinbase.models не считается, потому что это не класс, большое спасибо, теперь я знаю, почему. На самом деле я не могу обещать определение клиента, но я создал его экземпляр, а затем обещал модели, вот так, и это сработало: Promise.promisifyAll(client); Promise.promisifyAll(coinbase.model); - person Fdo; 20.04.2016

Итак, вместо того, чтобы снова редактировать вопрос, я добавляю свой временный обходной путь (с немного другим вызовом функции, но с той же проблемой отсутствия функции Async). Это обещает модули модели самостоятельно, и мне нужно будет создавать их по требованию всякий раз, когда мне нужна обещанная функция в необещанной версии моделей, возвращаемых клиентом.

Это не то, что я хотел бы сделать, поскольку для каждой модели, которую я хочу выполнить, требуется больше памяти. Но я предпочитаю этот подход созданию новых модулей для группировки new Promise(...) функций.

Если будет предложено лучшее решение, я все равно отмечу его как решенное.

var Promise = require('bluebird');
var Client = require('coinbase').Client;
var cbModel = require('coinbase').model;

var client = new Client({
  'apiKey': '<snip>',
  'apiSecret': '<snip>',
  'baseApiUri': 'https://api.sandbox.coinbase.com/v2/',
  'tokenUri': 'https://api.sandbox.coinbase.com/oauth/token'
});

Promise.promisifyAll(client);
Promise.promisifyAll(cbModel);

//Promises
client.getAccountAsync('primary')
.then(function(account) {
  account = new cbModel.Account(client, account);
  return account.getTransactionsAsync(null);
})
.then(function(transactions) {
  console.log('Transactions:');
  transactions.forEach(function(tx) {
    console.log(tx.id);
  });
})
.catch(function(err) {
  console.log(err);
});
person Fdo    schedule 20.04.2016