2013-11-11 4 views
13

Кажется, что в 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 
      });  
     }); 
     } 

    }; 

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

ответ

8

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

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

     }); 

}); 

Второй способ заключается в использовании обещания (я не был в курсе этого ранее)

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

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

10

Вы можете использовать Promises для этого. На самом деле это отличная утилита. Я использую Q, что является то, что Waterline (Sail's 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() функция должна возвращать обещание, стандартный искатель из парусов будет работать прозрачно (просто не передать функцию обратного вызова). Согласно this other question кажется, что стандартный искатель не ведет себя точно так же, как обещания Q, ответ, который я дал там, должен помочь получить более последовательное поведение.

More on Q and how it works in the doc !

+0

Существует довольно много дискуссий, чтобы избавиться от библиотеки Q, и вместо этого сделать это подключаемым, как ES6 pro mises, Bluebird и т. д. Смотрите: https://github.com/balderdashy/sails/issues/1186#issuecomment-56510067 – arcseldon

+0

@arcseldon Да, я был частью более старой дискуссии по Waterline по этому вопросу: https: // github. com/balderdashy/waterline/pull/238, но он никогда не сливался. Команда Sails не очень сильно относится к перфомансу и обещанию в целом. –

+0

@arcseldon на самом деле, они просто слили еще один запрос на тягу: https: // github.com/balderdashy/waterline/pull/487 # event-171216102 –

9

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

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

    } 
}; 
+0

или асинхронный параллельный, если запросы независимы – glasspill

4

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

первой установки Q

npm install q 

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

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

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

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

     // Finally let's 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); 
}); 
Смежные вопросы