将异步工作流更改为承诺(蓝鸟)



我一直在努力理解Promises。 对于基本概念我理解,但是一旦它被嵌套,我就有点困惑了。任何反馈都值得赞赏

这是我尝试重构为承诺的代码(蓝鸟)

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包装在返回承诺的东西中。许多 promise 库都有用于"承诺"异步函数的实用程序,但我认为这在这里不起作用,因为request在其回调中传递了两个成功值:

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

最新更新