猫鼬不使用Promise机制执行内部查询

时间:2018-11-05 22:33:25

标签: javascript node.js mongodb

我是异步/等待世界的新手,正在尝试对Mongoose + MongoDB + Node.JS进行一些试验 我有这段代码

exports.updateBrandPreferences = async (req,res) => {
    var userID = req.body.playerID;
    var newBrands = req.body.brandList;
    console.log("Ricevuto la seguente lista: " + newBrands);
    async.each(newBrands, function(brand,error) {
        Brand.findOneAndUpdate({'name': brand},{$addToSet: {peopleInterested: userID}}, {new:true}).exec().then((results) => {
            console.log(results);
            User.findOneAndUpdate({_id: userId},{$addToSet: {interestedBrands: results._id}}, {new:true}).exec().then((risultato)=> {
                console.log(risultato);
                return risultato;
            }).catch((err) => {
                return "error";
            });
            return results;
        }).catch((err) => {
            return "error";
        });
    });

    return res.status(200).json({"message": "OK"});
};

从请求中获取一些元素,我的目标是将指定用户与一些感兴趣的品牌列表相关联。尽管第一个查询有效(因此Brands现在内部有新用户来表示他们的兴趣),但由于第二个查询未执行,因此这对用户不起作用。
我想念什么?架构如下:
品牌

var BrandSchema = new Schema({
  name: {type: String, required: true, unique: true},
  peopleInterested: Array,
}, {
    collection: 'brands',
    retainKeyOrder: true,
    timestamps: true,
  }).plugin(mongoosePaginate);


用户

var UserSchema = new Schema({
  isAdmin: {type: Boolean, default: false},
  name: String,
  surname: String,
  email: { type: String, lowercase: true, required: true, trim: true, unique: true, dropDubs: true },
  password: { type: String, required: true },
  salt: { type: String },
  verified: { type: Boolean, default: false },
  bio: {
    type: { type: String, enum: [0,1] }, // 0='Squadra', 1='Giocatore'
    birthday: String,
    height: Number,
    number: Number,
    role: { type: String, enum: [0,1,2,3] }, // 0='Playmaker', 1='Ala', 2='Guardia', 3='Centro'
    team: String,
    city: String,
    fiscalCode: {type: String, maxlength:16}
  },
  newsletter: {type: Boolean, default: false},
  lastCheckin: {type: mongoose.Schema.Types.ObjectId, ref: 'Checkin'},
  follows: [{type: mongoose.Schema.Types.ObjectId, ref: 'Structure'}],
  interestedBrands: Array,
  score: { type: Number, default: 0 },
  profilePicture: String,
  lastLogin: {type: Date},
  facebook: {
    id: String,
    accessToken: String,
    profileImage : String
  }
}, {
  collection: 'users',
  retainKeyOrder: true,
  timestamps: true,
}).plugin(mongoosePaginate);

1 个答案:

答案 0 :(得分:1)

这是与this onethis one相同的问题。 async函数,async库和普通的Promise混合在一起。在回调中没有正确链接承诺。

async 功能(它是诺言的语法糖)和async async.each)解决了类似的任务,除非另有证明,否则不要混用。 async库是本机Promise的前身,它是基于回调的,可能会导致回调地狱;应有的承诺应该有所帮助(它们是基于回调的,但提供了一种有用的链接模式)。

async函数内部的承诺应该与awaitfor..of并行地与await和循环语句(Promise.all)一起处理。

Express没有意识到诺言。如this answer中所述,应该处理中间件内部的所有拒绝。

应该是:

exports.updateBrandPreferences = async (req, res, next) => {
  try {
    var userID = req.body.playerID;
    var newBrands = req.body.brandList;

    await Promise.all(newBrands.map(async (brand) => {
        await Brand.findOneAndUpdate({'name': brand},{$addToSet: {peopleInterested: userID}}, {new:true});

        await User.findOneAndUpdate({_id: userId},{$addToSet: {interestedBrands: results._id}}, {new:true});
    }));

    return res.status(200).json({"message": "OK"});
  } catch (err) {
    next(err);
  }
};