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

时间:2016-02-16 01:56:06

标签: javascript node.js asynchronous promise keystonejs

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

我在find / exec操作中丢失了返回状态。我已经尝试过promises,async等等。

如果有人能够指出实施此方法的正确方法,我将不胜感激。

一般实施:

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

2 个答案:

答案 0 :(得分:0)

对于初学者来说,exec是一个异步调用,你忽略了res.apiResponse,因此count递增而不是added,以使生活更轻松,我正在移动执行在外面打电话并用承诺包装它:

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

}

答案 1 :(得分:0)

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

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