skip to Main Content

I’m trying to consume 2 services from Ebay API:
findItemsByKeywords(keyword): return a list of items(object);
getItemTransactions(itemId): return a list of item’s transactions(object);

After calling findItemsByKeywords and get the returned items list, I need to call getItemTransactions and get the transactions for each one of that items and create a new list with them.

I’m using Node.js, Express, Ejs and MongoDB

My code works for one interaction only.

Error:
Error: unable to connect to database at mongodb://localhost/simplysell-development
    at NativeConnection.<anonymous> (/Users/guilhermefalcao/workspace/simplysell/app.js:11:9)
    at emitOne (events.js:96:13)
    at NativeConnection.emit (events.js:188:7)
    at Db.<anonymous> (/Users/guilhermefalcao/workspace/simplysell/node_modules/mongoose/lib/drivers/node-mongodb-native/connection.js:169:10)
    at emitTwo (events.js:106:13)
    at Db.emit (events.js:191:7)
    at Server.listener (/Users/guilhermefalcao/workspace/simplysell/node_modules/mongodb/lib/db.js:1786:14)
    at emitOne (events.js:96:13)
    at Server.emit (events.js:188:7)
    at Server.<anonymous> (/Users/guilhermefalcao/workspace/simplysell/node_modules/mongodb/lib/server.js:274:14)
    at emitOne (events.js:96:13)
    at Server.emit (events.js:188:7)
    at Pool.<anonymous> (/Users/guilhermefalcao/workspace/simplysell/node_modules/mongodb-core/lib/topologies/server.js:334:12)
    at emitOne (events.js:96:13)
    at Pool.emit (events.js:188:7)
    at Connection.<anonymous> (/Users/guilhermefalcao/workspace/simplysell/node_modules/mongodb-core/lib/connection/pool.js:270:12)

I’m not trying to access the database, I don’t know why this error.

I’m sorry about the code and english quality, I’m starting now.

Here is some code:

router.get('/bestsellers', (req, res, next) => {
  var i = 0;
  var findItemsByKeywordsPromise = findItemsByKeywords('iphone');
  findItemsByKeywordsPromise.then(items => {
    var getItemTransactionsPromise = getItemTransactions(items);
    return getItemTransactionsPromise;
  }).then(test => console.log(test))

});

function getItemTransactions(items) {

  return new Promise((resolve, reject) => {
    var list = [];
    items.forEach(function (item) {

      ebay.xmlRequest({
        serviceName: 'Trading',
        opType: 'GetItemTransactions',

        // app/environment
        devId: 'xxxxxxx',
        certId: 'xxxxxxx',
        appId: 'xxxxxxx',
        sandbox: false,

        // per user
        authToken: 'xxxxxxx',

        params: {
          'ItemID': item.itemId,
          'NumberOfDays': 30
        }
      }, function (error, results) {
        list.push(results)
        resolve(list);
      });
    })
  });

}

function findItemsByKeywords(keywords) {

  return new Promise((resolve, reject) => {

    var params = {
      keywords: [keywords],
    };

    ebay.xmlRequest({
      serviceName: 'Finding',
      opType: 'findItemsByKeywords',
      appId: 'xxxx',      // FILL IN YOUR OWN APP KEY, GET ONE HERE: https://publisher.ebaypartnernetwork.com/PublisherToolsAPI
      params: params,
      parser: ebay.parseResponseJson    // (default)
    },
      // gets all the items together in a merged array
      function itemsCallback(error, itemsResponse) {
        if (error) reject(error);

        console.log('findItemsByKeywords called');

        var items = itemsResponse.searchResult.item;

        console.log('Found', items.length, 'items');
        resolve(items);
      }
    );
  });
}

2

Answers


  1. Looking at the code we can’t know why that Mongo error is happening.

    But answering the answer in the title, the function getItemTransactions is wrong. You are calling resolve for each item in the array, but Promises can only be resolved once, so it will only give back the first item it resolves.

    I would organize it in two functions:

    function getItemTransaction (item) {
        return Promise(function (resolve, reject) {
            ebay.xmlRequest({
                serviceName: 'Trading',
                opType: 'GetItemTransactions',
    
                // app/environment
                devId: 'xxxxxxx',
                certId: 'xxxxxxx',
                appId: 'xxxxxxx',
                sandbox: false,
    
                // per user
                authToken: 'xxxxxxx',
    
                params: {
                    'ItemID': item.itemId,
                    'NumberOfDays': 30
                }
            }, function (error, results) {
                if (error) {
                    return reject(error);
                }
                resolve(results);
              });
        });
    }
    
    
    function getItemTransactions(items) {
        var promises = items.map(function(item) {
            return getItemTransaction(item);
        });
        // Promise.all waits for all the promises to get resolved
        // and return an array of resolved promises
        return Promise.all(promises);
    }
    

    The second function might not be necessary, if you do that operation in your main code:

    findItemsByKeywords('iphone')
        .then(items => {
            return Promise.all(items.map(item => getItemTransaction(item));
        })
        .then(test => console.log(test));
    
    Login or Signup to reply.
  2. That’s right. The loop finish before the ebay api returns a value, so the resolve will return an incomplete array (list).

    function getItemTransactions(items) {
    
      return new Promise((resolve, reject) => {
        var list = [];
        items.forEach(function (item) {
    
          ebay.xmlRequest({
            serviceName: 'Trading',
            opType: 'GetItemTransactions',
    
            // app/environment
            devId: 'xxxxxxx',
            certId: 'xxxxxxx',
            appId: 'xxxxxxx',
            sandbox: false,
    
            // per user
            authToken: 'xxxxxxx',
    
            params: {
              'ItemID': item.itemId,
              'NumberOfDays': 30
            }
          }, function (error, results) {
            list.push(results)
            if (list.length == items.length) {
              resolve(list);
            }
          });
        })
      });
    
    }
    

    This is what I change, I’m resolving when the list array is completed:

    if (list.length == items.length) {
        resolve(list);
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search