在以后的链条中使用第一个承诺的价值

我很想知道如何在Q promise中实现“链接”之间的共享价值,而不会完全亵渎承诺的美丽成语。

我使用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(); });; 

然而,将相同的模式应用于我的插入端点时,我遇到了一个问题。 我必须使用从第一个承诺返回的集合,即从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作为一个可能的解决scheme,但是这显然不能保证事件的顺序。

一旦你清理了variables命名,你可以在第一个Q.ninvoke之前的范围内声明一些东西。 在第一个callback中,将其分配给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! }) 

最好地捕捉您在closures中的后续步骤所需的值。 承诺可以嵌套在处理程序中。 then ,通过从处理程序返回一个承诺,保留顺序性,即使在嵌套链中也是如此。

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