2015-05-09 51 views
0

我最近开始为我的Node.js应用程序使用q promise javascript库。在我的代码中,我有一个条件来决定我是否应该执行1或3个承诺方法。然后我想执行promise-returns方法的数组并对结果执行额外的处理。如何使用Q Promise内部和外部的结果promise.spread

问题:如何使用.spread(...)内部和外部的结果,以便我可以将结果传递给其他方法?

一些背景:我正在构建一个REST API,其中取决于POST JSON正文的值,我必须先使用Sequelize将记录插入到数据库中,获取响应(所以我知道自动生成的主键),然后使用该主键将记录插入到其他表中。

var promiseMethods; 

var someParam1, someParam2, someParam3 = 'Hello World'; 

if (someCondition == true) { 

    promiseMethods = [promiseMethod1(someParam1)]; 
} else { 
    promiseMethods = [ 
     promiseMethod1(someParam1), 
     promiseMethod2(someParam2), 
     promiseMethod3(someParam3)]; 
} 

Q.all(promiseMethods) 
    .spread(function(promseResult1, 
        promiseResult2, 
        promiseResult3) { 

    var model = { 
     result: promiseResult1 
    }; 

    //Other code removed for brevity. 

    return DatabasePromise.save(model) 
}); 

我希望能够做一些类似于下面的假设代码。

var result = add(promiseResult1) 
var result2 = subtract(promiseResult2) 
var result3 = multiply(promiseResult3) 

基本上我想并行执行所述第一1或3承诺返回方法,然后能够此后使用在多次许的结果(S)。

下面是我希望代码执行的更好的想法。这里的示例是我有一个产品表,其中包含与该产品关联的用户。我想将数据插入这两个表(以及第三个表)。

var _ = require('lodash'); 

function insert(request, reply) { 

    var response; 

    var db = getDBConnection(); 

    var step1Promises; 

    if (property == true) { 

     step1Promises = [ 
      CommonModule.promiseMethodForProductUsers(db, userUUIDs) 
     ]; 

    } else { 

     step1Promises = [ 
      CommonModule.promiseMethodForProductUsers(db, userUUIDs), 
      CommonModule.promiseMethod2(payload.data1, payload.data2), 
      CommonModule.promiseMethod3(db, payload.data3) 
     ]; 
    } 

    var step1 = Q.all(step1Promises); 

    var resolvedProductUsers; 
    var internalIDs; 

    var productPromise = step1.spread(function(productUsers, promiseMethod2, promiseMethod3) { 

     resolvedProductUsers = productUsers; 

     var currentUser = users[0].uid; 

     internalIDs = Q(_.pluck(resolvedProductUsers, 'uid')); 

     var product = db.Product.build({ 
      product_name: productName, 
      last_edit_user_id: currentUser 
     }); 

     return CommonModule.createProduct(db, product); 
    }); 

    // When running, internalIDs is undefined. 
    var step2 = Q.all([ 
     CommonModule.buildProductUsersModel(db, internalIDs, productPromise.tid), 
     CommonModule.buildOtherTableModel(db, productPromise.pid, currentUser.Id, otherData) 
    ]); 

    step2.spread(function(usersToInsert, otherTableDataToInsert) { 

     CommonModule.saveProductUsers(db, usersToInsert); 
     CommonModule.saveOtherTableData(db, otherTableDataToInsert); 
    }); 

    // The response must be a promise, otherwise this insert method will finish 
    // and return an empty result. 
    response = productPromise; 

    return reply(response); 
} 
+0

你是什么意思的“访问超出'.spread'”?你想如何“将结果传递给其他方法”?你的代码的哪部分不起作用? – Bergi

+0

您不应将该数组命名为'promiseMethods'。当你在其构造中调用*单个promise-returning *方法*时,它是一组promise,而不是方法。 – Bergi

+0

@Bergi,我更新了我的问题的澄清。我希望它更有意义。关于你对'promiseMethods'的评论,我应该以不同的方式编写这个部分,或者只是把'name'改成'promises'? (尽管这只是示例代码,但它仍然有助于理解它是如何工作的。) – musubi

回答

1

您可以使用普通变量缓存点差的结果以备后用。

var result1, result2, result3; 
Q.all([ 
    method1, 
    method2, 
    method3 
]).spread(function(
    promiseResult1, 
    promiseResult2, 
    promiseResult3 
){ 
    result1 = promiseResult1; 
    result2 = promiseResult2; 
    result2 = promiseResult2; 
    ... 
    <do something with result1> 
}).then(function) { 
    // outside the spread 
    <do something with result2> 

    // 
    <do something with result3> 
}) 

您还可以使用嵌套闭包来访问父闭包的结果。

var result1, result2, result3; 
Q.all([ 
    method1, 
    method2, 
    method3 
]).spread(function(
    promiseResult1, 
    promiseResult2, 
    promiseResult3 
){ 
    return doSomethingWhichReturnsPromise(promiseResult1) 
    .then(function() { 
    <do something with promiseResult2> 
    }) 
    .catch(function() { 
    <do something with promiseResult3> 
    }) 
})