简体   繁体   English

Express&Nodejs:仅在创建模式后如何调用“ next()”

[英]Express & Nodejs : How to call 'next()' only after have created schemas

i'm build an event app, and in my 'Event' schema i've an array of 'Tag's schemas, so each event can have one or more tags. 我正在构建一个事件应用,在我的“事件”模式中,我有一个“标签”模式的数组,因此每个事件可以有一个或多个标签。

Event: 事件:

var EventSchema = new Schema({ 
...
tags: [{
 type: Schema.Types.ObjectId,
    ref: 'Tag'
  }],
...
}

And Tag: 和标签:

var TagSchema = new Schema({
  name:{
    type: String,
    require: true
  },
  times:{
    type: Number,
    default: 0
  }
});

When a user wants to create an event it sends a json to the /POST in the event middleware with all the information regarding the event and an array composed by 当用户想要创建事件时,它将向事件中间件中的/ POST发送json以及有关该事件的所有信息以及由

//json sent by client to server
{tags:[{name:tag1},{name:tag2}]

Since two events can't have the same name, in a specific middleware i check if some users has already created the tag or we need to actually store one. 由于两个事件不能使用相同的名称,因此在特定的中间件中,我检查是否某些用户已经创建了标签,或者我们实际上需要存储一个。

// add the tags
  addTags(req, res, next) {
    var myBody = req.body;
    if (myBody.tags) {
      const len = myBody.tags.length
      if (len > 0) {
        // we need to search and store a tag if is has not already created
        for (let i = 0; i < len; i++) {
          let currentTag = myBody.tags[i]
          // find the currentTag in the DB
          Tag.findOne({
            name: currentTag.name
          }, (err, find) =>{
            if (err) return next(err)
            // if we not find it
            else if (!find) {
              // create new one
              let newTag = new Tag({
                name: myBody.tags[i].name
              })
              utils.saveModel(newTag, next, (saved) => {
                // store it back the ref
                req.Event.tags.push(saved._id)
              })
            } else {
              // store the ref
              req.Event.tags.push(find._id)
            }
          })
        }
        console.log('tags added!.');
        next()
      }
    } else {
      next()
    }
  },

My problem is, how can i call the 'next' only after i've checked all the tags? 我的问题是,仅在检查完所有标签后才能如何调用“ next”? Is it possible? 可能吗? Thank you 谢谢

You can use Promise.all to wait for an array of promises to be fulfilled. 您可以使用Promise.all等待一系列诺言被兑现。

Code is untested but should give you the outline of a Promise solution. 代码未经测试,但应为您提供Promise解决方案的概述。

mongoose = require('mongoose');
mongoose.Promise = require('bluebird');

// Promise to add a new tag
function addTag(req, currentTag) {
  let newTag = new Tag({
    name: currentTag.name
  })
  return newTag.save()
    .then( (saved) => {
      // Store it back the ref
      return req.Event.tags.push(saved._id)
    })
}

// Promise to find a tag or add it.
function findTagOrAdd(req, currentTag) {
  return Tag.findOne({ name: currentTag.name})
    .then( (find) => {
      if ( find ) return req.Event.tags.push(find._id);
      // Otherwise create new one
      return addTag(req, currentTag);
    })
}

// Promise to add all tags.
function addTags(req, res, next) {
  var myBody = req.body;
  if ( ! myBody.tags ) return next();
  if ( ! Array.isArray(myBody.tags) ) return next();
  if ( myBody.tags.length <= 0 ) return next();

  // Promise to find the currentTag in the DB or add it.
  var promised_tags = [];
  myBody.tags.forEach( (currentTag) => {
    promised_tags.push( findTagOrAdd(req, currentTag) )
  }

  // Wait for all the tags to be found or created. 
  return Promise.all(promised_tags)
    .then( (results) => {
      console.log('tags added!.', results);
      return next();
    })
    .catch(next);
}

You probably should use promises , but if you don't want to change your current approach, you can do it the old fashioned way, by counting called callbacks: 您可能应该使用Promise ,但是如果您不想更改当前的方法,则可以通过计数被称为回调的旧方法来实现:

function addTags(req, res, next) {
  var myBody = req.body

  if (!myBody.tags || !myBody.tags.length) {
    next()
  }

  let errorOccured = false
  let checkedTags = 0

  for (let currentTag of myBody.tags) {
    Tag.findOne({ name: currentTag.name }, (err, find) => {
      if (errorOccured) {
        return
      }

      if (err) {
        errorOccured = true
        return next(err)
      }

      checkedTags += 1

      if (!find) {
         let newTag = new Tag({ name: currentTag.name })

         utils.saveModel(newTag, () => {}, (saved) => {
           req.Event.tags.push(saved._id)

           if (checkedTags === myBody.tags.length) {
             next()
           }
         })
      } else {
        req.Event.tags.push(find._id)

        if (checkedTags === myBody.tags.length) {
          next()
        }
      }
    })
  }
}

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

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