Keystone.js嵌套承诺 -> foreach -> 列表查找范围问题

keystone.js nested promise -> foreach -> list find scope issue

本文关键字:查找 范围 问题 列表 foreach 嵌套 Keystone js 承诺      更新时间:2023-09-26

我正在编写一个服务,其中我从另一个服务中检索项目列表,然后迭代执行keystone.list操作的结果。

我在查找/执行操作中丢失了返回状态。 我尝试过承诺、异步等。

如果有人能指出实现这一点的正确方法,我将不胜感激。

一般实现:

exports = module.exports = function (req, res) {      
    var rtn = {
           added: 0,
           count: 0
    }
    service(params)
        .then(function(svcResult) {
             svcResult.forEach(function(item) {
                    rtn.count++; // <-- correctly seen in apiresponse
                    Artifact.model.find()
                            .where({ artifactId: item.id})
                            .exec(function(err, result) {
                                    if (result.length == 0) { 
                                         result = new Artifact.model({
                                              ... populate from item ....
                                                });
                                         result.save();
                                         rtn.added++;  // <-- not seen in api response
                                     });
                     });
             res.apiResponse(rtn); 
            });
}

对于初学者来说,exec 是一个异步调用,您在res.apiResponse中忽略了它,因此count是递增而不是added ,为了让生活变得轻松,我将 exec 调用移到外面并用 promise 包装它:

function pExec(id){
  return new Promise(function(resolve, reject){
    Artifact.model.find()
      .where({ artifactId: id})
      .exec(function(err, result){
        console.log('result: ', result); // there is a possibility that this is not empty array, which seems to be the only case when you increment added value
        err? reject(err): resolve(result);
     });
  });
}

exports = module.exports = function(req, res){      // I think it is 'exports' not 'exposts'
  service(params)
    .then(function(svcResult) {
      var promises = svcResult.map(function(item){
        rtn.count++;
        return pExec(item.id).then(function(result){
          if (result.length == 0) { 
            result = new Artifact.model({
              //... populate from item ....
            });
            result.save(); // again this might be an async call whose response you might need before incrementing added...
            rtn.added++;  // <-- not seen in api response
          };        
        });
      });
      Promise.all(promises).then(function(){
        res.apiResponse(rtn); 
      });
    });
}

谢谢...这是我到目前为止想出的....

function getArtifact(id) {
    return new Promise(function (resolve, reject) {
        Artifact.model.findOne()
            .where({artifactId: id})
            .exec(function (err, artifact) {
                err ? resolve(null) : resolve(artifact);
            });
    });
}
function createArtifact(item) {
    return new Promise(function (resolve, reject) {
        var artifact = new Artifact.model({
            // ... populate from item ....
        });
        artifact.save(function (err, artifact) {
            err ? resolve(null) : resolve(artifact);
       });
   });
}
exports = module.exports = function (req, res) {
var rtn = {
    success: false,
    count: 0,
    section: '',
    globalLibrary: {
        Added: 0,
        Matched: 0
    },
    messages: [],
};
if (!req.user || !req.user._id) {
    rtn.messages.push("Requires Authentication");
    return res.apiResponse(rtn);
}
if (!req.params.section) {
    rtn.messages.push("Invalid parameters");
    return res.apiResponse(rtn);
}
var userId = req.user._id;
var section = req.params.section;
rtn.section = section;
service(section)
    .then(function (svcResult) {
        if (svcResult.length == 0 || svcResult.items.length == 0) {
            rtn.messages.push("Retrieved empty collection");
            return;
        }
        rtn.messages.push("Retrieved collection");
        var artifacts = svcResult.items(function (item) {
            rtn.count++;
            return getArtifact(item.objectid)
                .then(function (artifact) {
                    if (!artifact || artifact.length == 0) {
                        rtn.messages.push("Global Library Adding: " + item.name['$t']);
                        rtn.globalLibrary.Added++;
                        artifact = createArtifact(item);
                    } else {
                        rtn.globalLibrary.Matched++;
                    }
                    return artifact;
                })
        });
        Promise.all(artifacts)
            .then(function () {
                rtn.success = true;
                res.apiResponse(rtn);
            });
    });
}