简体   繁体   English

sails.js bluebird 承诺链接多个查询很慢

[英]sails.js bluebird promise chaining multiple query slow

I am new to node.js/ sails.js.我是 node.js/sails.js 的新手。 I heard node.js is very fast.我听说 node.js 非常快。 But i am getting very poor performance.但我的表现很差。 Here i have used bluebird for promise.Basically i want to refactor this so it will be faster.在这里,我使用 bluebird 作为 promise。基本上我想重构它,这样它会更快。 Here i am executing four different query for getting product details(name,model,description etc), product additional images , product options and each options details.在这里,我正在执行四种不同的查询来获取产品详细信息(名称、型号、描述等)、产品附加图像、产品选项和每个选项的详细信息。

I want to know how can i split these four query to four different methods or functions so i can reuse these later and also when i will call get getProductdetails this will call all four query and get end results faster.我想知道如何将这四个查询拆分为四个不同的方法或函数,以便我可以稍后重用它们,并且当我调用 get getProductdetails 时,这将调用所有四个查询并更快地获得最终结果。 Please help me on this.请帮我解决这个问题。 I am stuck to proceed further.我坚持要进一步。 Many thanks in advance.提前谢谢了。

// api/model/product.js
    getProductDetails:function(product_id){
        return new Promise(function(resolve, reject) {
            var product={},options=[];
            //details
          Product.query("select * from product p , product_description pd where p.product_id="+product_id+" and pd.product_id= p.product_id and pd.language_id=1",function(error, details) {
            //images    
            Product.query("SELECT * FROM product_image WHERE product_id = "+product_id+" ORDER BY sort_order ASC",function(error, images) { 

            //options   
            Product.query("SELECT * FROM product_option po LEFT JOIN `option` o ON (po.option_id = o.option_id) LEFT JOIN option_description od ON (o.option_id = od.option_id) WHERE po.product_id = "+product_id+" AND od.language_id = '1' ORDER BY o.sort_order",function(error, options) {
                    options.forEach(function (item) {
                                //options value
                              Product.query("SELECT * FROM product_option_value pov LEFT JOIN option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_id = "+product_id+" AND pov.product_option_id = "+item.product_option_id+" AND ovd.language_id = '1' ORDER BY ov.sort_order",function(error,option_value){
                                    options.push({options: item, option_value: option_value});
                                });
                        });//foreach option
                product={details:details[0], options: options, images:images};
                resolve(product);
            }); 

        });

        });

        }); 
    }   

Node is "fast" for certain workloads and patterns. Node 对于某些工作负载和模式来说是“快速的”。 A lot of it's speed comes from the way it handles IO and network tasks ( such as database queries ) which increase it's ability to handle scale.它的很多速度来自它处理 IO 和网络任务(例如数据库查询)的方式,这增加了它处理规模的能力。 [If you are interested in reading more about that and how it works read about the Event Loop - here is a good article] [如果您有兴趣阅读有关事件循环的更多信息及其工作原理,请阅读事件循环 -是一篇很好的文章]

As far as improving your provided code goes - I have made the assumption you are using Bluebird and have installed Underscore.js to make it slightly neater.至于改进您提供的代码 - 我假设您使用 Bluebird 并安装了 Underscore.js 以使其更简洁。 For security reasons I would highly recommend switching to an ORM or at least making sure you escape the information in the SQL query.出于安全原因,我强烈建议切换到 ORM 或至少确保您转义 SQL 查询中的信息。 Node is fast but does not solve injection issues :) Node 速度很快,但不能解决注入问题:)

I have refactored your code so that request can execute in parallel which should help to speed up your code by leveraging concurrency as in any other language.我已经重构了您的代码,以便请求可以并行执行,这应该有助于通过利用任何其他语言的并发性来加速您的代码。 I have used promises and also taken advantage of the bluebird promisify all system so that you don't need to create a Promise.我使用了 Promise 并且还利用了 bluebird promisify all 系统,这样您就不需要创建 Promise。

var promisifiedProduct = Promise.promisifyAll(Product)
var _ = require('underscore')

getProductDetails: function(product_id) {

    var details_retriever = promisifiedProduct.queryAsync("select * from product p, product_description pd where p.product_id=" + product_id + " and pd.product_id= p.product_id and pd.language_id=1")

    var images_retriever = promisifiedProduct.queryAsync("SELECT * FROM product_image WHERE product_id = " + product_id + " ORDER BY sort_order ASC")

    var options_retriever = promisifiedProduct.queryAsync("SELECT * FROM product_option po LEFT JOIN `option` o ON (po.option_id = o.option_id) LEFT JOIN option_description od ON (o.option_id = od.option_id) WHERE po.product_id = " + product_id + " AND od.language_id = '1' ORDER BY o.sort_order")

    // Iterate over each option for some additional information
    var sub_options_retriever = options_retriever.then(function(options) {

        // Map the options to a Promise that will resolve to the value
        var sub_option_retrievers = _.map(options, function (option) {

            // Return a Promise that resolves to the desired object
            return  promisifiedProduct.queryAsync("SELECT * FROM product_option_value pov LEFT JOIN option_value ov ON (pov.option_value_id = ov.option_value_id) LEFT JOIN option_value_description ovd ON (ov.option_value_id = ovd.option_value_id) WHERE pov.product_id = " + product_id + " AND pov.product_option_id = " + option.product_option_id + " AND ovd.language_id = '1' ORDER BY ov.sort_order")
                .then(function(sub_options) {

                    return {
                        options: option, 
                        option_value: sub_options
                    }

                })

        })

        // Concurrently retrieve the sub options
        return Promisify.all(sub_option_retrievers)

    })

    // Wait for all the information to be retrieved
    var retriever = Promisify.all([details_retriever, images_retriever, options_retriever, sub_option_retriever])

    var result_formatter = retriever.then(function(results) {

        // Create a scope level variable for options so we are not mutating a provided argument
        var options = results[2]

        // Add each sub_option into options - Not sure why?
        var formatted_options = _.forEach(result[3], function(sub_option) {
            options.push(sub_option)
        })

        return {
            details: results[0][0],
            options: formatted_options, 
            images: results[1]
        }
    })

    return result_formatter
}

I haven't tested the code or double checked any of the functions so it may need a little tweaking but it should be good!我还没有测试代码或仔细检查任何功能,所以它可能需要一些调整,但它应该是好的!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM