BreezeJS - 链接查询

时间:2013-12-10 23:48:54

标签: javascript breeze q

假设我们有一个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
 });

1 个答案:

答案 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。我必须考虑到CustomercustId没有{{1}}的可能性。