假设我们有一个Customer对象,它有一个“Foo”集合。我希望我的“getCustomer”函数添加它已经没有的所有Foos,然后返回自己,作为一个承诺......
所以我想承诺:获得一个客户,然后将所有缺少的Foos添加到该客户,这样当承诺得到解决时,客户就会失去所有的抱负。
示例:
// dataservice.js
// returns Q.Promise<breeze.QueryResult>
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers").where("CustomerId", "==", custId);
return this.em.executeQuery(query);
}
// returns Q.Promise<breeze.QueryResult>
function getFoosNotOnCustomer(customer) {
var query = breeze.EntityQuery().from("Foo").where("CustomerId", "!=", customer.Id());
return this.em.executeQuery(query);
}
我正在努力如何正确地“链接”这些,如果找不到客户怎么办,等等。我如何修改“getCustomer”来做到这一点?我基本上试图同步使用breeze。这是我的尝试,但它很快变成了丑陋的嵌套代码。
// want to return Q.Promise<Customer> that has Foos loaded
// I think this is actually returning something like Q.Promise<Q.Promise<Customer>>
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId);
return this.em.executeQuery(query) // return here?
.then(function(data) {
// what about conditionals?
if(data.results.length == 1) {
getFoosNotOnCustomer(data.results[0]).
then(function (foosArray) {
$.each(foosArray, function(i,el) {
// push foos onto customer instance
}
return custWithFoos; // return here?
}
// return something?
}
}
}
这是我最终做的事情:
function getCustomer(custId) {
var query = breeze.EntityQuery().from("Customers").where("CustomerId", "==", custId);
return manager.executeQuery(query) // return here?
.then(addFoos)
.then(doSomethingElse);
}
function addFoos(data) {
var myDefer = Q.Defer();
if (data && data.result.length == 1) {
var customer = data.results[0];
var query = // get FOOS Customer doesn't have;
manager.executeQuery(query).then(function (fooData) {
$.each(fooData.results function (i, el) {
customer.Foos.push(el);
});
myDefer.reslove(customer);
});
} else {
myDefer.resolve(undefined);
}
return myDefer.promise;
}
function doSomethingElse(customer) {
var myDefer = Q.Defer();
customer.SomePropert("test");
return myDefer.resovlve(customer);
}
// ----- MVVM
var custPromise = getCustomer(1).then(function (customer) {
// do something
});
答案 0 :(得分:2)
尽管我无法理解语义,但我会以面值为例...特别是我无法理解为什么让所有不属于客户的Foo会有所帮助。
我只关注“链接”,我假设您希望调用者在完成后占用所选客户。
在此示例中,我们在获取Foos之前等待客户
function getCustomer(custId) {
var cust;
var em = this.em;
var query = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId);
// On success calls `gotCustomer` which itself returns a promise
return em.executeQuery(query)
.then(gotCustomer)
.fail(handleFail); // you should handleFail
// Called after retrieving the customer.
// returns a new promise that the original caller will wait for.
// Defined as a nested success function
// so it can have access to the captured `cust` variable
function gotCustomer(data) {
cust = data.results[0];
if (!cust) {
return null; // no customer with that id; bail out now
}
// got a customer so look for non-customer foos
// returning another promise so caller will wait
return breeze.EntityQuery().from("Foos")
.where("CustomerId", "!=", custId)
.using(em).execute()
.then(gotFoos);
}
// Now you have both the customer and the other Foos;
// bring them together and return the customer.
function gotFoos(data) {
var foos = data.results;
// assume `notMyFoos` is an unmapped property that
// should hold every Foo that doesn't belong to this Customer
foos.forEach(function(f) { cust.notMyFoos.push(f); }
return cust; // return the customer to the caller after Foos arrive.
}
}
在您的方案中,您在获取foos之前不必等待客户查询。您从一开始就了解客户和foos的选择标准。 假设您认为客户查询很可能会返回客户,您可以并行启动两个查询,然后在两个查询完成时混搭数据。考虑一下Q.all
。
function getCustomer(custId) {
var em = this.em;
var custPromise = breeze.EntityQuery().from("Customers")
.where("CustomerId", "==", custId)
.using(em).execute();
var fooPromise = breeze.EntityQuery().from("Foos")
.where("CustomerId", "!=", custId)
.using(em).execute();
Q.all([custPromise, fooPromise])
.then(success)
.fail(handleFail); // you should handleFail
// Now you have both the customer and the "other" Foos;
// bring them together and return the customer.
// `data` is an array of the results from each promise in the order requested.
function success(data) {
var cust = data[0].results[0];
if (!cust) return null;
var foos = data[1].results;
// assume `notMyFoos` is an unmapped property that
// should hold every Foo that doesn't belong to this Customer
foos.forEach(function(f) { cust.notMyFoos.push(f); }
return cust; // return the customer to the caller after Foos arrive.
}
}
请注意,我不必在成功路径中进行太多的空检查。调用成功回调时,我保证有data.results
。我必须考虑到Customer
与custId
没有{{1}}的可能性。