我可以在另一个诺言中召集承诺(带循环)吗?



我正在尝试从eBay API中消费2个服务: findItemsByKeywords(keyword):返回项目列表(对象); getItemTransactions(itemId):返回项目的交易列表(对象);

拨打findItemsByKeywords并获取返回的项目列表后,我需要致电getItemTransactions并获取每个项目的交易并与它们创建新列表。

我正在使用node.js,express,ejs和mongodb

我的代码仅适用于一种交互。

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)

我不是要访问数据库,我不知道为什么这个错误。

我对代码和英语质量感到抱歉,我现在开始

这是一些代码:

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);
      }
    );
  });
}

查看代码,我们不知道为什么会发生mongo错误。

但是回答标题中的答案,函数 getItemTransactions是错误的。您正在为数组中的每个项目调用resolve,但是承诺只能解决一次,因此它只会回馈其解决的第一项。

我将以两个功能组织:

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);
}

如果您在主代码中执行该操作,则第二个功能可能不是必需的:

findItemsByKeywords('iphone')
    .then(items => {
        return Promise.all(items.map(item => getItemTransaction(item));
    })
    .then(test => console.log(test));

是正确的。eBay API返回值之前的循环完成,因此解决方案将返回不完整的数组(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);
        }
      });
    })
  });
}

这是我更改的,当列表阵列完成时,我正在解决:

if (list.length == items.length) {
    resolve(list);
}

最新更新