Подтвердить что ты не робот

Как выполнить несколько запросов в контроллере sailsjs?

Кажется, что в sailsjs вы можете запускать и передавать только один набор данных запроса за раз. Например, вот контроллер моей домашней страницы:

     module.exports = {

       index: function (req, res) {

        Blog.find()
        .limit(3)
        .sort('createdAt desc')
        .where({ isPublished: 1 })
        .exec(function(err, posts) {
          if (err) return next(err);
          res.view({
            layout: "homeLayout",
            posts:posts
          });    
        });  
      }

    };

Как я могу запросить данные из какой-либо другой модели и передать ее моему представлению вместе с данными блога, которые я уже пропустил?

4b9b3361

Ответ 1

Я выяснил несколько способов добиться этого. Первый способ заключается в том, чтобы вложить ваши запросы, например.

Blog.find()
  .limit(30)
  .sort('createdAt desc')
  .where({ isPublished: 1 })
  .exec(function(err, posts) {

        SomeOtherModel.find()
        .limit(5)
        .sort('createdAt desc')
        .where({ isPublished: 1 })
        .exec(function(err, otherdata) {

          res.view({
            posts: posts,
            otherdata: otherdata
          });

      });

}); 

Второй способ - использовать promises (об этом я раньше не знал)

 User.findOne()
.where({ id: 2 })
.then(function(user){
    var comments = Comment.find({userId: user.id}).then(function(comments){
        return comments;
    });
    return [user.id, user.friendsList, comments];
}).spread(function(userId, friendsList, comments){
    // Promises are awesome!
}).fail(function(err){
    // An error occured
})  

Третий способ (я закончил с этим) - создать политику (специфичную для sailsjs, но являющуюся прямым промежуточным программным обеспечением)

 // saved as /api/policies/recentPosts.js
 // also need to add a rule to /config/policies.js
 module.exports = function (req, res, ok) {

       Blog.find()
        .limit(3)
        .sort('createdAt desc')
        .where({ isPublished: 1 })
        .exec(function(err, footerposts) {

            res.footerposts = footerposts;
            return ok();
      });           
 };

Выполняя это так, вам не нужно передавать что-либо вашему мнению, но я не уверен, что его хорошая практика случайным образом добавляет данные в объект ответа.

Ответ 2

Вы можете использовать Promises для этого. Это на самом деле отличная утилита. Я использую Q, что означает Waterline (Sail ORM) используется за сценой.

Ниже приведен пример кода, в котором я извлекаю данные из первой модели, а затем, используя полученные данные, я запрашиваю другие модели, чтобы получить еще несколько данных (параллельно), и в конце я отправляю результат возвращается к представлению.

      SomeModel.findOne(criterias).then(function(result) {
        Q.all([
          SomeOtherModel.getSomething(result),
          YetAnotherModel.getSomethingElse(result)
        ]).spread(function(someOtherResult, yetAnotherResult) {
          var data = {
            thing: result,
            stuff: someOtherResult,
            otherthing: yetAnotherResult
          };
          return res.view(data);
        });
      }).fail(function(reason) {
        return res.view(reason);
      });

Функция getSomething() должна вернуть обещание, standard finder из Sails будет работать прозрачно (просто не передавайте обратный вызов). По this другой вопрос, похоже, что стандартный искатель не ведет себя точно так же, как Q promises, ответ, который я дал там, должен помочь получить более последовательное поведение.

Подробнее о Q и о том, как это работает в документе!

Ответ 3

Вы также можете использовать async.auto(см. ниже). Здесь ссылка для полного примера репозитория парусов.

var async = require('async'),
    _ = require('lodash');

module.exports = {


    index: function (req, res) {

        async.auto({

            // Get the blog posts
            posts: function (cb) {
                Blog.find()
                    .where({ isPublished: 1 })
                    .limit(5)
                    .sort('createdAt DESC')
                    .exec(cb);
            },


            // Get some more stuff
            // (this will happen AT THE SAME TIME as `posts` above)
            otherThings: function (cb) {
                OtherThing.find()
                    .limit(30)
                    .exec(cb);
            },


            // Get comments
            // (we'll wait until `posts` is finished first)
            comments: ['posts', function (cb, async_data) {

                // Get `posts`
                // (the second argument to cb() back in `posts`)
                // Used map to make sure posts are an array of ids and not just an object. 
                var posts = async_data.posts.map(function (item){ return item.id});

                // Get comments that whose `post_id` is equal to 
                // the id of one of the posts we found earlier
                Comment.find()
                    .where({ post_id: posts })
                    .exec(cb);
            }]

        },
        function allDone (err, async_data) {

            // If an error is passed as the first argument to cb
            // in any of the functions above, then the async block
            // will break, and this function will be called.
            if (err) return res.serverError(err);

            var posts = async_data.posts;
            var comments = async_data.comments;

            var otherThings = async_data.otherThings;

            // Fold the comments into the appropriate post
            // An in-memory join
            _.map(posts, function (post) {
                var theseComments =
                    _.where(comments, { post_id: post.id });
                post.comments = theseComments;

            });

            // Show a view using our data
            res.json({
                // layout: 'homeLayout',
                posts: posts,
                otherThings: otherThings
            });
        });

    }
};

Ответ 4

Итак, вот как вы можете сделать 3 запроса и передать все свои данные в свое представление:

сначала установите Q

npm install q

Затем используйте код ниже и замените мои модели своими:

// first import Q
var Q = require('q');

// Let combine results of 3 queries
Q.all([
      // let find one user with name "Pavel"
      User.findOne({name: 'Pavel'}).then(),

      // let find one Lexus car
      Cars.findOne({brand: 'Lexus'}).then(),

      // Finally let get the first Apple phone
      Phones.findOne({brand: 'Apple'}).then()
    ])
.spread(function (user, car, phone) {
  // Output results as json, but you can do whatever you want here
  res.json([user, car, phone]);
}).fail(function (reason) {
  // output reason of failure
  res.json(reason);
});