【问题标题】:Change async workflow to Promise (Bluebird)将异步工作流程更改为 Promise (Bluebird)
【发布时间】:2015-03-17 17:53:50
【问题描述】:

我一直在尝试围绕 Promise 进行思考。对于我理解的基本概念,但是一旦嵌套,我就会有点困惑。任何反馈表示赞赏

这是我试图重构为 Promises (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);

【问题讨论】:

  • 那么,问题是什么?

标签: javascript node.js asynchronous promise bluebird


【解决方案1】:

首先要做的是将request 包装在一个返回承诺的东西中。许多 promise 库都有用于“promisifying”异步函数的实用程序,但我认为这不会在这里起作用,因为 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
});

【讨论】:

    猜你喜欢
    • 2014-09-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-24
    • 1970-01-01
    相关资源
    最近更新 更多