2016-02-11 18 views
9

Tôi đang sử dụng alt để thực hiện thông lượng cho dự án và đang gặp khó khăn trong việc xử lý các cửa hàng tải cho hai thực thể liên quan. Tôi đang sử dụng tính năng sources cùng với registerAsync để xử lý các cuộc gọi async/api của tôi và liên kết chúng với các chế độ xem của tôi bằng AltContainer.Phụ thuộc dữ liệu Flux/Alt, cách xử lý một cách tao nhã và độc đáo

Tôi có hai thực thể liên quan từ một đến một bởi cuộc hội thoạiId. Cả hai đều được nạp thông qua một cuộc gọi api:

enter image description here

Khi cửa hàng công việc của tôi được nạp với dữ liệu tôi muốn điền vào một cửa hàng trò chuyện.

tôi sử dụng một nguồn để nạp các cửa hàng công việc:

module.exports = { 
    fetchJobs() { 
     return { 
      remote() { 
       return axios.get('api/platform/jobs'); 

      },.... 

Có vẻ như một công việc cho các WAITFOR() phương pháp, nhưng có vẻ như để sử dụng khi nội dung của một cửa hàng đòi hỏi một sự chuyển đổi hoặc sáp nhập với nội dung của người khác. Tôi cần tìm nạp nội dung của một kho dữ liệu dựa trên nội dung của một kho dữ liệu khác.

Nói chung tôi cần phải:

  • Gọi một bên thứ ba và API tải một danh sách các thực thể vào một cửa hàng.
  • Khi dữ liệu đó đến, tôi cần phải sử dụng thuộc tính từ mỗi bên trên để gọi một API khác và tải dữ liệu đó vào một cửa hàng khác.

Giải pháp ngây thơ của tôi là tham chiếu các hoạt động trò chuyện từ cửa hàng việc làm và gửi sự kiện khi dữ liệu đến. Một cái gì đó như thế này:

var jobActions = require('../actions/Jobs'); 
var conversationActions = require('../actions/Conversations'); 

class JobStore { 
    constructor() { 
     this.bindListeners({ 
      handlefullUpdate: actions.success 
     });... 

    } 

    handlefullUpdate(jobs) { 
     this.jobs = jobs; 
     conversationActions.fetch.defer(jobs); 
    } 
} 

Tất nhiên, vi phạm nguyên tắc không lưu trữ sự kiện và vì vậy tôi phải trì hoãn gửi một hành động ở giữa công văn. Nó có ý nghĩa đối với tôi, vì dường như đi xuống con đường này tôi đang giới thiệu lại tất cả các loại tác dụng phụ trong mã của tôi; mất đi vẻ đẹp của "đường ống chức năng" mà tôi nên thấy với thông lượng.

Ngoài ra, cửa hàng công việc của tôi phải giữ một tham chiếu đến bất kỳ thực thể phụ thuộc nào để nó có thể gửi hành động thích hợp. Ở đây tôi chỉ có một, nhưng tôi có thể tưởng tượng nhiều. Xét về sự phụ thuộc giữa các thực thể, điều này có vẻ hoàn toàn ngược.

Một vài lựa chọn thay thế tôi suy nghĩ:

Tôi có thể gọi api/nền tảng/công việc endpoint trong nguồn/hành động mà tôi lấy tất cả các cuộc hội thoại, chỉ để có được định danh. Cách tiếp cận ban đầu là hiệu quả hơn, nhưng điều này có vẻ tinh tế hơn với tinh thần thông lượng mà tôi mất tất cả các cuộc nói chuyện chéo.

Tôi cũng có thể có một hành động/nguồn đơn lẻ tìm nạp cả hai, trả lại {jobs:{}, conversations: in the action} (dàn xếp phụ thuộc ở đó bằng cách sử dụng lời hứa) và sử dụng điều này cư trú cả hai cửa hàng. Nhưng cách tiếp cận này có vẻ phức tạp không cần thiết đối với tôi (tôi cảm thấy mình không nên làm điều đó!).

Nhưng tôi có thiếu một cách khác không? Có vẻ kỳ lạ rằng một trường hợp sử dụng phổ biến như vậy sẽ phá vỡ sự tao nhã của thiên lý thông lượng và/hoặc buộc tôi phải nhảy qua rất nhiều vòng lặp.

@dougajmcdonald đặt ra một câu hỏi tương tự here, nhưng có lẽ nó đã được phrased quá thường, và không nhận được bất kỳ lực kéo:

Trả lời

0

Tôi đã xem câu trả lời của @ gravityplanx, nhưng tôi không chắc chắn nó cải thiện tình hình như thế nào.

Để nhắc lại và khuếch đại: Tôi thực sự, thực sự thích mẫu alt tải cửa hàng của tôi từ một nguồn. Mỗi thành phần cần một (các) cửa hàng trông giống như vậy:

export default class extends React.Component { 
    componentDidMount() { 
     CurrentUser.fetch(); 
     Jobs.fetch(); 
    }; 
    render() {  
     return(
      <AltContainer stores={{user:CurrentUser, jobs:Jobs}}> 
       <Body/> 
      </AltContainer>) 
    } 

} 

Mục đích là dễ hiểu trong nháy mắt. Và tôi nhận được sự phân tách rõ ràng về các mối quan tâm, giúp việc kiểm tra hành động/cửa hàng và nguồn của tôi dễ dàng hơn.

Nhưng mô hình đẹp phân tích trong trường hợp sử dụng phổ biến từ câu hỏi của tôi và tôi phải tạo ra một số đường ống khá phức tạp trong hành động và cửa hàng của mình để dàn xếp cuộc gọi ajax cho các cuộc hội thoại. Câu trả lời khác dường như chỉ thay đổi sự phức tạp này ở nơi khác. Tôi muốn nó biến mất.

Điều tôi làm là làm sao để phân biệt hoàn toàn các cửa hàng (giải pháp đầu tiên được đề xuất trong câu hỏi). Tôi thực hiện cuộc gọi ajax bổ sung để tìm cuộc trò chuyệnId và công việc khác để tìm nạp các cuộc hội thoại trong nguồn JobConversation. Một cái gì đó như thế này:

axios.get(window.taxFyleApi + 'api/platform/active-jobs-pick/layerConversation?jobId=' + jobId) 
      .then((res)=> { 
       let job = res.data[0]; //Returns an array with only one item 
       let qBuilder = window.layer.QueryBuilder.messages().forConversation(job.conversationId)... 

Tôi giữ nguyên cách sử dụng AltContainer với các thành phần của tôi và mất tất cả hệ thống ống nước. Ngay bây giờ, tôi nghĩ rằng sự rõ ràng kết quả là giá trị gọi lại kết thúc thêm.

Tôi cũng nhận ra cách tôi muốn LIKE nó hoạt động (về ký hiệu) và sẽ hỏi @goatslacker, hoặc có thể tự chụp. Tôi muốn có thể chỉ định sự phụ thuộc trong phương thức exportAsync() trên một cửa hàng. Tôi rất muốn có thể nói:

class JobConvesationStore { 
    constructor() { 
     this.exportAsync(source, JobStore); 
    } 

Phương pháp không đồng bộ JobConversationStore sẽ không được gọi cho đến khi JobStore có dữ liệu. Mục đích dễ đọc và không cần phải có vũ đạo hành động phức tạp.

0

Giải pháp tốt nhất mà tôi đã đến với với cho đến nay (và một trong những rằng các ví dụ dường như làm theo) là thêm hành động "jobsFetched" vào tác vụ công việc của tôi và gửi nó khi dữ liệu đến.

var jobActions = require('../actions/Jobs'); 
var ConversationActions = require('../actions/Conversations'); 

class JobStore { 
    constructor() { 
     this.bindListeners({ 
      handlefullUpdate: jobActions.success... 
     });... 

    } 

    handlefullUpdate(jobs) { 
     this.jobs = jobs; 
     ConversationActions.jobsFetched.defer(jobs); 
    } 
} 


class ConversationStore { 
    constructor() { 
     this.bindListeners({ 
      handleJobUpdate: jobActions.jobsFetched... 
     });... 

    } 

    handleJobUpdate(jobs) { 

     /*Now kick off some other action like "fetchConversations" 
      or do the ajax call right here?*/ 

    } 

} 

này giúp loại bỏ các vấn đề của các cửa hàng công việc cần phải giữ một tham chiếu đến tất cả các đối tượng phụ thuộc của nó, Nhưng tôi vẫn phải gọi một hành động từ bên trong cửa hàng của tôi, và tôi phải giới thiệu hành động jobsFetched đó thiết lập các ConversationStore để lấy dữ liệu của nó. Vì vậy, có vẻ như tôi không thể sử dụng nguồn cho các cuộc trò chuyện của mình.

Có ai có thể làm tốt hơn không?

1

Điều này chắc chắn có vẻ giống như một lỗ hổng trong thiết kế thông lượng và bạn nói đúng, đây là trường hợp sử dụng rất phổ biến. Tôi đã nghiên cứu vấn đề này (và một vài vấn đề tương tự) trong vài ngày nay để thực hiện tốt hơn Flux trong hệ thống của riêng tôi, và trong khi có những lựa chọn chắc chắn, hầu hết đều có nhược điểm.

Giải pháp phổ biến nhất dường như đang sử dụng Vùng chứa, chẳng hạn như AltContainer, để xóa đi nhiệm vụ dữ liệu yêu cầu từ apis và tải từ các cửa hàng vào một thành phần duy nhất, không có logic. Container này sẽ chịu trách nhiệm xem thông tin từ các cửa hàng và xác định xem các hành động bổ sung có bắt buộc phải hoàn thành hay không. Ví dụ;

static getPropsFromStores() { 
    var data = SomeStore.getState(); 
    if (/*test if data is incomplete */){ 
     SomeAction.fetchAdditionalData(); 
    } 
    return data; 
} 

Có ý nghĩa. Chúng ta có logic và thành phần trong lớp Component của chúng ta, nơi Flux nói nó thuộc về nó.

Cho đến khi bạn xem xét khả năng có hai vùng chứa được yêu cầu cho cùng một thông tin (và do đó sao chép bất kỳ lần tìm nạp khởi tạo nào, tức là cuộc hội thoại trong mô hình của bạn) và sự cố chỉ tồi tệ hơn nếu bạn thêm thứ ba (hoặc thứ tư hoặc thứ năm) container truy cập vào các cửa hàng đó.

Câu trả lời soạn trước đó từ đám đông vùng chứa là "Chỉ cần không có nhiều hơn một!", Đó là lời khuyên tuyệt vời ... nếu yêu cầu của bạn là ok với điều đó.

Vì vậy, đây là giải pháp thay đổi của tôi, xung quanh cùng một khái niệm; Bao gồm một thùng chứa/thành phần chính xung quanh toàn bộ ứng dụng của bạn (hoặc thậm chí bên cạnh ứng dụng). Không giống như các thùng chứa truyền thống, Vùng chứa/Thành phần chính này sẽ không thuộc tính lưu trữ cho con của nó. Thay vào đó, chỉ có chỉ chịu trách nhiệm về tính toàn vẹn và hoàn thành dữ liệu.

Dưới đây là triển khai mẫu;

class JobStore { 
    constructor() { 
     this.bindListeners({ 
      handleJobUpdate: jobActions.success 
     }); 

    }, 

    handleJobUpdate(jobs) { 
     this.jobs = jobs;    
    } 
} 

class ConversationStore { 
    constructor() { 
     this.bindListeners({ 
      handleJobUpdate: jobActions.success, 
      handleConversationUpdate: conversationActions.success 
     }); 

    }, 

    handleJobUpdate(jobs) { 
     this.conversations = {}; 
     this.tmpFetchInfo = jobs.conversation_id; 
     this.isReady = false; 

    }, 

    handleConversationUpdate(conversations) { 
     this.conversations = conversations; 
     this.tmpFetchInfo = ''; 
     this.isReady = true; 
    } 

} 

class MasterDataContainer { 

    static getPropsFromStores() { 
     var jobData = JobStore.getState(); 
     var conversationData = ConversationStore.getState(); 

     if (!conversationData.isReady){ 
      ConversationAction.fetchConversations(conversationData.tmpFetchInfo); 
     } 
    }, 

    render: function(){ 
     return <div></div>; 
    } 
} 
+0

Tôi sẽ xem xét mã của bạn khi đầu của tôi rõ ràng hơn. Cảm ơn. –

+0

Tôi đã tặng bạn một món quà. Không có ý nghĩa trong những điểm đi xa. –

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