【问题标题】:sequential queries from database using sequalize in node+express在 node+express 中使用 sequelize 从数据库进行顺序查询
【发布时间】:2018-07-19 00:30:13
【问题描述】:

我刚刚开始节点并且来自 PHP 背景。一段时间以来,我一直试图弄清楚 Promise,但无法弄清楚。

我试图在循环中的第二个查询中使用一个查询的结果,但有两个问题:

-ONE:typeof 值显示一个对象;但是当我安慰它时,它显示未定义

-二:我的结果没有按正确的顺序排列。我正在尝试使用 'then()' 但无法完全弄清楚。 “inside promise 2”在 'then()' 1 块中的循环之前被安慰

这是我在代码中所做的:

exports.followers_temp = function(req, res)
{
    db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users"  INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE  public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset',  { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT}).
    then(function(data){
      console.log('i am here; length: ' + data.length);
        return new Promise(function(resolve, reject) {
              console.log('inside promise 1, should have access to data object');

              console.log('before loop');
              for(let i=0; i < data.length; i++){
                  var temp = db.sequelize.query('(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = ' + data[i].user_id + ' AND public."Followships".follower_id = :my_id)',  { replacements: { leader_id: req.params.leader_id, my_id: req.params.my_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT})
                  temp.then(function(value){

                    // Issue ONE
                      console.log('type: '+ typeof value); // it's an object
                      console.log('is_following: '+ value.is_following); // yet it's giving undefined

                      console.log('value: '+ JSON.stringify(value)); // but it prints out when I stringify it

                      data[i].is_followed = value.is_following;
                  });
              }
            resolve(data);
            });
    })

    .then(function(my_array){
        // Issue TWO
        console.log('inside promise 2');

        return res.status(200).send({
            error:false,
            message: my_array
        });
    })
        .catch(function(err) {
            console.log('inside promise catch');
            return res.status(400).send({
                error:true,
                message: errorHandler.getErrorMessage(err)
            });
        });
};

这是控制台输出:

i am here; length: 5          
inside promise 1, should have 
before loop                   
inside promise 2              
type: object                  
is_following: undefined       
value: [{"is_following":"1"}] 
type: object                  
is_following: undefined       
value: [{"is_following":"0"}] 
type: object                  
is_following: undefined       
value: [{"is_following":"1"}] 
type: object                  
is_following: undefined       
value: [{"is_following":"1"}] 
type: object                  
is_following: undefined       
value: [{"is_following":"0"}] 

请告诉我 -我究竟做错了什么? - 如果你能明智地使用 Promise 语法......那就太好了

感谢您的期待;请忽略菜鸟的错误,因为我现在是菜鸟。

【问题讨论】:

  • 循环和承诺不能很好地混合。而是使用Promise.all
  • hmm... Promise.all --- 这对我来说是一个新术语... 我会研究它的功能并在我理解它的情况下尝试使用它。谢谢你的提示。

标签: javascript node.js express npm sequelize.js


【解决方案1】:

在更深入地搜索 stackoverflow 之后,我能够解决我的问题。我使用了 THIS POST 上提供的帮助。

感谢 stackoverflow 社区提供的所有帮助。今后我也会努力做出贡献的。

最终解决方案如下所示:

    exports.followers_temp = function (req, res) {
    db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users"  INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE  public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset', { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT })
        .then(function (users) {
            var promises = users.map(function(user){
                return db.sequelize.query(
                    '(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = ' +
                    user.user_id + ' AND public."Followships".follower_id = :my_id)',
                    { replacements:
                            { leader_id: req.params.leader_id,
                                my_id: req.params.my_id,
                                limit: req.params.limit,
                                offset: req.params.offset
                            },
                        type: db.sequelize.QueryTypes.SELECT
                    })
                    .then(function(results){
                        user.is_followed = results[0].is_following;
                        return user
                    })
            })
            Promise.all(promises).then(function(results) {
                return res.status(200).send({
                    error: false,
                    message: users
                });
            })
                .catch(function (err) {
                    return res.status(400).send({
                        error: true,
                        message: errorHandler.getErrorMessage(err)
                    });
                });
        })
    .catch(function (err) {
        return res.status(400).send({
            error: true,
            message: errorHandler.getErrorMessage(err)
        });
    });
};

【讨论】:

    【解决方案2】:

    如果你已经有一个promise,你不需要使用new Promise

    exports.followers_temp = function (req, res) {
      db.sequelize.query('SELECT DISTINCT public."Users".id as user_id, public."Users".full_name, public."Users".profile_image_url, (SELECT COUNT(*) FROM public."Followships" WHERE public."Followships".leader_id = public."Users".id AND public."Followships".follower_id = :leader_id) AS is_followed FROM public."Users"  INNER JOIN public."Followships" ON public."Users".id = public."Followships".follower_id WHERE  public."Followships".leader_id = :leader_id LIMIT :limit OFFSET :offset', { replacements: { leader_id: req.params.leader_id, limit: req.params.limit, offset: req.params.offset }, type: db.sequelize.QueryTypes.SELECT })
      .then(function (users) {
        console.log('i am here; length: ' + users.length);
        //do not use new Promise if you already have a promie
        //https://stackoverflow.com/a/48576246/1641941
        //use promise.all and map data to promises
        return Promise.all(
          users.map(
            user=>{
              db.sequelize.query(
                '(SELECT COUNT(*) AS is_following FROM public."Followships" WHERE public."Followships".leader_id = :leader_id AND public."Followships".follower_id = :my_id)', 
                { replacements: 
                  { leader_id: user.user_id,//changed leader_id
                    my_id: req.params.my_id//removed limit and offset 
                  },
                  type: db.sequelize.QueryTypes.SELECT 
                })
                .then(function (value) {
                  console.log('type: ' + typeof value);
                  //value is an array
                  console.log('is_following: ' + value[0].is_following);
                  console.log('value: ' + JSON.stringify(value));    
                  user.is_followed = value[0].is_following;
                  return user;
                });
            }
          )
        )
      })
      .then(function (users) {
        // Issue TWO
        console.log('inside promise 2',users);
        return res.status(200).send({
          error: false,
          message: users
        });
      })
      .catch(function (err) {
        console.log('inside promise catch',err);
        return res.status(400).send({
          error: true,
          message: errorHandler.getErrorMessage(err)
        });
      });
    };
    

    【讨论】:

    • 感谢您的帮助...我看到了一种很好的编码风格,将遵循它,但您的代码在打印其他数据之前仍在打印“inside promise 2”,即:“我在这里;长度: 5 在承诺 2 [未定义,未定义,未定义,未定义,未定义] 类型:对象 is_following:0 值:[{“is_following”:“0”}] 类型:对象 is_following:0 值:[{“is_following”:“0 "}] type: object is_following: 0 value: [{"is_following":"0"}] ...你怎么知道它是一个数组,而 typeof 正在显示对象?
    • 我认为您在第二个查询中犯了一个错误,将 leader_id 替换为 request.params.leader_id,将更新分析器。我知道它是一个对象,因为数组是对象(typeof [] 是“对象”)你的问题表明它是:value: [{"is_following":"1"}] 一个对象是 {} 一个数组是 [] 一个数组中的一个对象是:[{}]
    • o 是的,数组是 javascript 中的一个对象...在第二个查询中甚至没有使用 leader_id,它是多余的。我最后删除了 then() 并尝试在 promise.all 的末尾发送响应,但它说“标头已发送”......可能是因为循环。我仍在尝试修复它,修复后会在此处发布...
    【解决方案3】:

    db.sequelize.query 是放在for 循环中的异步调用。这将启动查询,但尚未成功完成。因此,您的 data 尚未完成,您已经在解决它。使用Promise.all 可以这样写:

    Promise.all(data.map((val) => { // here val = data[i] inside the query
        return new Promise((resolve, reject) => {
            db.sequelize.query(...)
                .then((value) => {
                    // modify your data object here.
                    resolve();
                });
        });
    })).then(() => { resolve(data);});
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-20
      • 2019-10-02
      • 1970-01-01
      • 2013-09-15
      • 2020-04-11
      • 2020-04-30
      • 2017-07-17
      • 2017-03-17
      相关资源
      最近更新 更多