async forEach循环进行api调用

时间:2013-09-22 18:48:57

标签: node.js asynchronous google-api

我有一个函数进行api调用,第二个函数循环遍历第一个函数的数据,并在每次迭代时调用api。我正在尝试使用异步库来实现这一点,但第二个函数仍然是异步运行而不是等待完成。所以我最终运行功能1运行,功能2启动,但最终回调在功能2完成之前运行。

async.series([
        function (callback) {
          //api call
          getShelves.execute(function (err, shelves) {
            if (err) { return callback(err); }
            async.forEach(shelves.items, function (shelf, callback) {
              var shelfObj = {id: shelf.id, title: shelf.title, books: []};
              bookShelves.push(shelfObj);
              callback();
            });

            //sort numerically to make placing books easier
            bookShelves.sort(function (a, b) {return a.id - b.id; });
            callback();
          });
        },
        function (callback) {
          async.forEach(bookShelves, function (shelf, callback) {
            //api call
            getBooks.execute(function (err, books) {
              if (err) { return callback(err); }
              if (books.items) {
                async.forEach(books.items, function (book, callback) {
                  var bookObj = {title: book.volumeInfo.title};
                  bookShelves[shelf.id].books.push(bookObj);
                  callback();
                });
              }
              callback();
            });
          });
          callback();
        }
      ], function (err) {
        if (err) { console.log('error'); }
        res.render('collection', { shelves: bookShelves });
      });
    });

编辑:现在感谢工作人员

function (callback) {
          async.forEach(bookShelves, function (shelf, callback) {
            getBooks.execute(function (err, books) {
              if (err) { return callback(err); }
              if (books.items) {
                async.forEach(books.items, function (book, callback) {
                  var bookObj = {title: book.volumeInfo.title};
                  bookShelves[shelf.id].books.push(bookObj);
                  console.log(book.volumeInfo.title);

                  //callback to continue book loop
                  callback();
                }, function () {
                  //callback to continue shelf loop
                  callback();
                });
              }else{
                callback();
               }
            });
          }, function () {
            //callback to end function and move to next. However this is never reached
            callback();
          });
        }

2 个答案:

答案 0 :(得分:1)

你的系列中的第二个函数会立即调用它的回调,而不是等到async.forEach迭代完成。相反,请尝试以后调用它:

    function (callback) {
      async.forEach(bookShelves, function (shelf, callback) {
        //api call
        //... skipped ...
      }, function() {
          callback();
      });
    }

答案 1 :(得分:0)

function loadShelf(shelf, callback) {
  //_.pick is handy for this FYI
  var shelfObj = {id: shelf.id, title: shelf.title};
  //presumably your getBooks call takes a shelf id to relate the
  //getBooks is an asynchronous DB or API call presumably
  getBooks(shelf.id, function (error, books) {
    if (error) {
      callback(error);
      return;
    }
    //This is an in-memory array. No async needed.
    shelfObj.books = books.map(function (book) {
      return {title: book.volumeInfo.title};
    });
    callback(null, shelfObj);
  });
}

getShelves.execute(function (error, dbShelves) {
  if (error) {
    res.render('error', error); //pseudo-code error handling
    return;
  }
  async.each(dbShelves, loadShelf, function (error, fullShelves) {
    if (error) {
      res.render('error', error); //pseudo-code error handling
      return;
    }
    //sort numerically to make placing books easier
    var sortedShelves = fullShelves.sort(function (a, b) {return a.id - b.id; });
    res.render('collection', { shelves: sortedShelves });
});