2012-11-28 19 views
6

Câu hỏi đặt ra: Làm thế nào tôi có thể cấu trúc mã của tôi để các bindings loại trực tiếp không được áp dụng cho đến khi tất cả các thắc mắc cho ViewModel đã được thực hiện?knockout.js applybindings sau khi truy vấn khoe js hoàn

Cập nhật: Sau một số nghiên cứu và thử nghiệm tiếp theo, tôi nghĩ rằng việc sử dụng thứ gì đó dọc theo dòng của hàm Trì hoãn có thể hoạt động. Tôi đã thử một vài triển khai, tuy nhiên nó chỉ bảo vệ cho đến khi truy vấn được gọi, thay vì cho đến khi tất cả kết quả truy vấn đã được xử lý. Tôi rõ ràng đang làm điều gì đó sai ở đây nhưng foo javascript của tôi là yếu.

Công nghệ sử dụng: Entity Framework 5 w/Oracle, Net 4 Web API, Knockout 2.2, Breeze 0.71.3

Tình hình: Breeze đang được sử dụng để gọi một phương thức Web API mà lấy một Số lượng các POCO, điền vào một mảng có thể quan sát được loại trực tiếp, và mảng được liên kết với một điều khiển chọn trong Dạng xem.

Vấn đề: Các truy vấn dễ dàng chưa hoàn thành và các quan sát loại trực tiếp chưa được điền trước khi áp dụng các ràng buộc ViewModel cho Chế độ xem. Khi kết quả truy vấn được trả về, giao diện người dùng không phản hồi trong 5 - 7 giây trong khi ko thể quan sát được và do đó điều khiển chọn được cập nhật. Dựa vào khai thác gỗ này dường như là vấn đề ...

File cshtml:

<select data-bind="options: $root.brokers, value: 'id', optionsText: 'name'"> 
<script data-main="/BrokerCommission/Scripts/app/main" src="/BrokerCommission/Scripts/require.js"></script> 

main.js:

requirejs.config(
    { 
     // well-know paths to selected scripts 
     paths: { 
      'breeze': '../breeze.debug', // debug version of breeze 
      'text': '../text'// html loader plugin; see http://requirejs.org/docs/api.html#text 
     } 
    } 
); 

define(['logger', 'text', 'breeze'], function(logger) { 

require(['vm.muni'], 
function() 
{ 
    logger.info('applying bindings'); 
    ko.applyBindings(my.vm); 
}); 

vm.muni là ViewModel của tôi tập tin javascript. Dưới đây là một phương pháp được tiếp xúc với exec một truy vấn:

getAllBrokers = function() { 
     dataservice.getBrokers() 
      .then(processBrokerQueryResults) 
      .fail(handleQueryErrors); 
    }, 

    processBrokerQueryResults = function (data) { 
     logger.info("Start loading Brokers " + Math.round(new Date().getTime()/1000)); 
     my.vm.brokers([]); 
     $.each(data.results, function (i, d) { 
      brokers.push(new my.Broker() 
       .id(d.id) 
       .name(d.name) 
      ); 
     }); 
     logger.info("End loading Brokers " + Math.round(new Date().getTime()/1000)); 
    }, 

đây là truy vấn gió từ dataservice.js file:

function getBrokers() { 
    var query = new entityModel.EntityQuery() 
      .from("GetBrokers") 
      //.orderBy("name"); 
    return manager.executeQuery(query); 
}; 

Trả lời

5

Một vài suy nghĩ xảy ra với tôi:

  1. tôi hiếm khi đẩy từng người một vào observableArray. Quá nhiều cập nhật DOM. Tạo một mảng tạm thời thay thế và cập nhật observableArray với điều đó. Tôi tin rằng đây là câu trả lời cho vấn đề hiệu suất mà bạn đang hỏi.

  2. Thiết lập phương thức khởi tạo khởi tạo trả về lời hứa khi tất cả các phương thức tải không đồng bộ ban đầu hoàn tất.

  3. Trì hoãn ko.applyBindings cho đến khi lời hứa khởi tạo thành công.

  4. Cân nhắc hiển thị hình chữ nổi + spinner trong khi đợi quá trình khởi tạo kết thúc.

  5. Cố gắng không làm quá nhiều trong quá trình khởi tạo.

Tôi không thể chỉ cho bạn cách thực hiện tất cả những điều này trong câu trả lời này. Tôi sẽ chỉ cho bạn số 1 ở đây và giới thiệu bạn "Fetch on Launch" trong tài liệu cho # 2. Tìm kiếm trên web + thử nghiệm là bạn của bạn cho phần còn lại.

Cập nhật observableArray với một mảng
 
processBrokerQueryResults = function (data) { 
     ... 
     var tempArray = [] 
     $.each(data.results, function (i, d) { 
      tempArray.push(dtoToBroker(d)); 
     }); 
     brokers(tempArray); 
     ... 

     // I prefer named fns to long lambdas 
     function dtoToBroker(dto) { 
      return new my.Broker() 
        .id(d.id) 
        .name(d.name); 
     } 

Tôi thích sử dụng các ECMAScript 5 Array.map cú pháp mà trả về một mảng sau khi áp dụng một chức năng để mỗi phần tử của một mảng nguồn. Vì vậy, tôi muốn viết:

 
processBrokerQueryResults = function (data) { 
     ... 
     brokers(data.results.map(dtoToBroker)); 
     ... 
} 
+0

Điều này hoàn toàn giải quyết được vấn đề! Các mảng temp đã làm các trick. Ngoài ra, cảm ơn bạn đã phản hồi kỹ lưỡng, các mẹo và tài nguyên khác. Tôi chỉ bắt đầu với cả hai loại trực tiếp và khoe khoang và mong muốn tìm hiểu cách thích hợp để cấu trúc các ứng dụng này. Các javascript có thể nhận ra tay một cách nhanh chóng. –

+0

Tôi hoàn toàn hiểu :) Bạn có thể không cần các công cụ RequireJS. Tôi rất thích nó. Nhưng ứng dụng này tiên tiến và nhiều ứng dụng có thể phù hợp với mô hình mô đun ít phức tạp hơn (ví dụ: "Tiết lộ mô-đun"). Bạn có thể đi từ đó trở lại Yêu cầu mà không cần nỗ lực rất lớn. Chúc may mắn! – Ward

Các vấn đề liên quan