将asynchronous工作stream更改为Promise(Bluebird)

我一直在试图把我的头围绕诺言。 对于我理解的基本概念,一旦嵌套,我有点困惑。 任何反馈意见

这里是我试图重构到承诺(蓝鸟)的代码

var getIndividualData = function(url, doneGetIndividualData) { var $, data; request(url, function(err, res, body) { if (!err && res.statusCode === 200) { $ = cheerio.load(body); data = { title: $("#itemTitle").children()["0"].next.data, condition: $("#vi-itm-cond").text(), price: $("#prcIsum_bidPrice").text(), imgUrl: $("#icImg")[0].attribs.src, createdAt: chance.date(), likes: chance.integer({min: 0, max: 1000}) }; doneGetIndividualData(null, data); } else { doneGetIndividualData(err); } }); }; var getListing = function(url, doneGetListing) { var $; var links = []; request(url, function(err, res, body) { if (!err && res.statusCode === 200) { $ = cheerio.load(body); $('.vip').each(function(i, el) { if (i < 15) { links.push(el.attribs.href); } }); async .concat(links, getIndividualData, function(err, result) { return doneGetListing(null, result); }); } else { doneGetListing(err); } }); }; var putToMongo = function(err, result) { if (devConfig.seedDB) { mongoose.connect(devConfig.mongo.uri); Item.find({}).remove(function(err, items) { Item.create(result, function(err, items) { console.log('done'); process.kill(); }); }); } }; async .concat(urls, getListing, putToMongo); 

要做的第一件事就是将request包装在返回承诺的东西中。 许多承诺库有“promisifying”asynchronous函数的工具,但我不认为这会在这里工作,因为request传递两个成功值到它的callback:

 var requestAsync = function(url) { return new Promise(function (resolve, reject) { request(function (err, res, body) { if (err) { reject(err); } resolve({ res: res, body: body}); }); }); }; 

一旦完成,它变得更容易:

 var getIndividualData = function(url) { return requestAsync(url).then(function (result) { if (result.res.statusCode === 200) { var $ = cheerio.load(result.body); return { title: $("#itemTitle").children()["0"].next.data, condition: $("#vi-itm-cond").text(), price: $("#prcIsum_bidPrice").text(), imgUrl: $("#icImg")[0].attribs.src, createdAt: chance.date(), likes: chance.integer({min: 0, max: 1000}) }; } throw new Error("Individual data status code: " + result.res.statusCode); }); }; var getListing = function(url, doneGetListing) { return requestAsync(url).then(function (result) { if (result.res.statusCode === 200) { var $ = cheerio.load(result.body), promises = $('.vip').filter(function (i) { return i < 15; }).map(function (i, el) { return getIndividualData(el.attribs.href); }); return Promise.all(promises); } throw new Error("Listing status code: " + result.res.statusCode); }); }; var putToMongo = function(result) { if (devConfig.seedDB) { mongoose.connect(devConfig.mongo.uri); Item.find({}).remove(function(err, items) { Item.create(result, function(err, items) { console.log('done'); process.kill(); }); }); } }; Promise.all(urls.map(getListing)) .then(putToMongo) .catch(function (err) { // handle error });