Node.js从do while循环中调用异步函数

时间:2017-01-17 09:30:19

标签: javascript node.js asynchronous async-await do-while

我想在do while循环中调用异步函数,只有在函数没有返回值时才退出。 有没有办法管理这个,而不必在回调之外实际等待

这里的代码显然总是在第一个循环中退出,因为在评估while()时函数还没有被回调:



var i = 0;
do {
  var foundListing;
  if (i) {
    listing.slug = listing.slug + '-' + (i + 1);
  }
  listingService.getListingBySlug(listing, function(error, pFoundListing) {
    if (error) {
      return callback(util.errorParser(error));
    } else if (Object.keys(pFoundListing).length) {
      foundListing = pFoundListing;
      i++;
    }
  });
  //Do I have to wait here???
} while (foundListing && Object.keys(foundListing).length);




澄清: 这里的要点是生成一个独特的slug。如果slug已经存在,我会附加一个数字并再次检查它是否存在。当我找到尚未存在的号码时,我已经完成了。

更新 我发现了一种使用递归的方法。我将工作代码段发布为answer

3 个答案:

答案 0 :(得分:1)

我没有测试它的可能性,但也许递归函数应该这样做:



const listingService = {
  getListingBySlug(listing, callback) {
    setTimeout(() => {
      if (listing.slug === 'listing-5') {
        callback(
          false,
          {
            name: 'Listing 1',
            slug: 'listing-1',
          }
        );
      }
      else {
        callback(false, {});
      }
    }, 1000);
  },
};

function checkListingExists(slug) {
  return new Promise((resolve, reject) => {
		const listing = { slug };
    listingService.getListingBySlug(listing, (error, pFoundListing) => {
      if (error) {
        reject(error);
      } else if (Object.keys(pFoundListing).length) {
        resolve(pFoundListing);
      } else {
        resolve(false);
      }
    });
  });
}

function nextListing(prefix, index) {
  checkListingExists(prefix + '-' + index)
  .then((listing) => {
    if (listing === false) {
      nextListing(prefix, index + 1);
    } else {
      console.log(listing);
    }
  })
  .catch(() => {
    // deal with error response
  });
}

nextListing('listing', 0);




答案 1 :(得分:0)

在这种情况下你应该使用诺言。你可以这样做。

    var DEFERRED = require('deferred');
    var deferred = new DEFERRED();
    var i =0;

    while(1) {      
      listingService.getListingBySlug(listing, function(error, pFoundListing) {
    if (error) {
      return callback(util.errorParser(error));
      deferred.reject();
      break;
    } else if (Object.keys(pFoundListing).length) {         
      i++;
      listing.slug = listing.slug + '-' + (i + 1); 
      if(pFoundListing) {deferred.resolve()}
      break;
    }
  });


  deferred.promise.then(function() {
    // You will have the listing.slug value here.
  });

顺便说一句,你不应该使用Object.keys()来确定对象是否为空。只需在utils文件中的某处创建自己的isEmpty方法并检查属性。如果您的pFoundListing非常大,则会出现严重的性能问题。对于小对象(数组),您不会注意到差异。

答案 2 :(得分:0)

我按照Giacomo Cosimato的建议使用递归工作。

以下是有效的摘录:

listingController.js



saveListing: function(listing, callback) {
  listingService.findOpenSlug(listing, listing.slug, 1, function(error, listing) {
    if (error) {
      return callback(util.errorParser(error));
    } else {
      listingService.saveListing(listing, function(error, savedListing) {
        //do some work
      });
    }
  });
}




listingService.js



var classMethods = {
  findOpenSlug: function(listing, baseSlug, i, callback) {
    listingRepository.getListingBySlug(listing.slug, function(error, foundListing) {
      if (error) {
        return callback(error);
      } else if (Object.keys(foundListing).length) {
        listing.slug = baseSlug + '-' + (i + 1)
        i++;
        classMethods.findOpenSlug(listing, baseSlug, i, callback);
      } else {
        callback(null, listing);
      }
    });
  },
  [...]
}