在后面的链接链接中使用第一个承诺的值

时间:2013-11-21 20:57:54

标签: javascript node.js promise q

我想知道如何在Q promises中完成“链接链接”之间的共享价值,而不会完全贬低承诺的相当成语。

我正在使用Q在mongo数据库上做一些逻辑。我的GET端点逻辑看起来很棒:

return Q.ninvoke(this.db, 'collection', 'namespace')
  .then(function(namespaceCollection){
    return Q.ninvoke(namespaceCollection,'findOne',{"name":name})
  }).then(function(queryResults){
    if(!queryResults){
      throw new providerErrors.NotFound();
      return
    }
    return queryResults;
    },function(err){
      throw new providerErrors.BadRequest();
    });;

然后将相同的模式应用于我的插入端点,我遇到了一个问题。我必须使用从第一个promise返回的集合,即从db对象获取集合的集合,以便将值保存回来:

return Q.ninvoke(this.db,'collection','namespace')
  .then(function(namespaceCollection){
     return Q.ninvoke(namespaceCollection,findOne,{"name":namespace.name}); 
  })
  .then(function(foundNamespace){
    if(namespace){
      throw new providerErrors.Conflict();
      return
    }
    //This is a new namespace object, give it a datetime and then
    //let's save it!
    namespace.createDate = new Date();
  })
  .then(function(namespaceToSave){
    //uhoh!  no collection in scope down here, just the value to persist!
  })

我想知道解决这个问题的最佳,最惯用的方法是什么。我探讨Q.all作为一种可能的解决方案,但这显然无法确保事件的顺序。

2 个答案:

答案 0 :(得分:1)

一旦清理了变量命名,就可以在第一个Q.ninvoke之前在范围内声明一些东西。在第一个回调中,将其分配给CB值,然后在第三个命名空间中使用它。

var namespaceCollection = null;
return Q.ninvoke(this.db,'collection','namespace')
  .then(function(namespaceCol){
     namespaceCollection = namespaceCol;
     return Q.ninvoke(namespaceCollection,findOne,{"name": namespace.name}); 
  })
  .then(function(foundNamespace){
    if(!foundNamespace){
      throw new providerErrors.Conflict();
      return
    }
    //This is a new namespace object, give it a datetime and then
    //let's save it!
    namespace.createDate = new Date();
  })
  .then(function(namespaceToSave){
    // namespaceCollection is now available!
  })

答案 1 :(得分:1)

最适合捕获闭包中后续步骤所需的值。 Promise可以嵌入处理程序中。顺序性由then保留,即使在嵌套链中也存在,通过从处理程序返回一个promise。

return Q.ninvoke(this.db,'collection','namespace')
  .then(function(namespaceCollection){
    return Q.ninvoke(namespaceCollection,'findOne',{"name":namespace.name}); 
    .then(function(foundNamespace){
      return // presumably returning a promise for the namespace
             // to save here, otherwise, `then` chaining is unnecessary
    })
    .then(function(namespaceToSave){
      // namespaceCollection is in scope
    })
  })