BreezeJS-链接查询

BreezeJS - Chaining Queries

本文关键字:查询 链接 BreezeJS-      更新时间:2024-07-04

假设我们有一个客户对象,它有一个"Foo"集合。我希望我的"getCustomer"函数添加它没有的所有Foo,然后返回它自己,作为一个承诺。。。

所以我想要一个承诺:获取一个客户,然后将所有缺失的Foo添加到此客户,这样当承诺得到解决时,客户就拥有所有缺失的foo。

示例:

// 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"来做到这一点?我基本上是在尝试同步使用微风。这是我的尝试,但它很快就变成了丑陋的嵌套代码。

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

尽管我无法理解语义,但我还是会以你的面值为例。。。尤其是我无法理解为什么让所有不属于客户的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.
    }
}

并行异步查询

在您的场景中,您真的不必在获得foo之前等待客户查询。您从一开始就知道客户和foo的选择标准假设您认为客户查询返回客户的可能性很高,您可能会并行启动两个查询,然后在两个查询完成时将数据混合。考虑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。我必须考虑到custId没有Customer的可能性。