Thứ năm, 18/04/2019 | 00:00 GMT+7

Cách tạo thanh tìm kiếm với RxJS

Lập trình phản ứng là một mô hình liên quan đến các stream dữ liệu không đồng bộ , trong đó mô hình lập trình coi mọi thứ là một stream dữ liệu trải rộng theo thời gian. Điều này bao gồm các lần nhấn phím, yêu cầu HTTP, file sẽ được in và thậm chí cả các phần tử của một mảng, có thể được coi là được tính giờ trong repository ảng thời gian rất nhỏ. Điều này làm cho nó hoàn toàn phù hợp với JavaScript vì dữ liệu không đồng bộ là phổ biến trong ngôn ngữ này.

RxJS là một thư viện phổ biến để lập trình phản ứng trong JavaScript . ReactiveX , chiếc ô mà RxJS nằm dưới đó, có các phần mở rộng của nó trong nhiều ngôn ngữ khác như Java , Python , C ++ , SwiftDart . RxJS cũng được sử dụng rộng rãi bởi các thư viện như Angular và React.

Việc triển khai RxJS dựa trên các hàm chuỗi có khả năng nhận biết và xử lý dữ liệu trong một phạm vi thời gian. Điều này nghĩa là người ta có thể triển khai hầu như mọi khía cạnh của RxJS mà không có gì khác hơn là các hàm nhận danh sách các đối số và lệnh gọi lại, sau đó thực thi chúng khi được ra hiệu làm như vậy. Cộng đồng xung quanh RxJS đã thực hiện công việc nặng nhọc này và kết quả là một API mà bạn có thể trực tiếp sử dụng trong bất kỳ ứng dụng nào để viết mã sạch và có thể bảo trì.

Trong hướng dẫn này, bạn sẽ sử dụng RxJS để xây dựng thanh tìm kiếm giàu tính năng trả về kết quả theo thời gian thực cho user . Bạn cũng sẽ sử dụng HTML và CSS để định dạng thanh tìm kiếm. Kết quả cuối cùng sẽ như sau:

Trình diễn Thanh tìm kiếm

Một cái gì đó phổ biến và có vẻ đơn giản như thanh tìm kiếm cần có nhiều bước kiểm tra khác nhau. Hướng dẫn này sẽ chỉ cho bạn cách RxJS có thể biến một bộ yêu cầu khá phức tạp thành mã dễ quản lý và dễ hiểu.

Yêu cầu

Trước khi bắt đầu hướng dẫn này, bạn cần những thứ sau:

Mã đầy đủ cho hướng dẫn có sẵn trên Github .

Trong bước này, bạn sẽ tạo và tạo kiểu cho thanh tìm kiếm bằng HTML và CSS. Mã sẽ sử dụng một vài yếu tố phổ biến từ Bootstrap để tăng tốc quá trình cấu trúc và tạo kiểu cho trang để bạn có thể tập trung vào việc thêm các yếu tố tùy chỉnh. Bootstrap là một khung công tác CSS chứa các mẫu cho các phần tử phổ biến như kiểu chữ, biểu mẫu, nút, chuyển , lưới và các thành phần giao diện khác. Ứng dụng của bạn cũng sẽ sử dụng Animate.css để thêm hoạt ảnh vào thanh tìm kiếm.

Bạn sẽ bắt đầu bằng cách tạo một file có tên search-bar.html bằng nano hoặc editor yêu thích của bạn:

  • nano search-bar.html

Tiếp theo, tạo cấu trúc cơ bản cho ứng dụng của bạn. Thêm HTML sau vào file mới:

search-bar.html
<!DOCTYPE html> <html>    <head>     <title>RxJS Tutorial</title>     <!-- Load CSS -->      <!-- Load Rubik font -->      <!-- Add Custom inline CSS -->    </head>    <body>       <!-- Content -->        <!-- Page Header and Search Bar -->        <!-- Results -->        <!-- Load External RxJS -->        <!-- Add custom inline JavaScript -->       <script>        </script>   </body>  </html> 

Vì bạn cần CSS từ toàn bộ thư viện Bootstrap, hãy tiếp tục và tải CSS cho Bootstrap và Animate.css.

Thêm mã sau vào phần Load CSS comment :

search-bar.html
... <!-- Load CSS -->     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css" /> ... 

Hướng dẫn này sẽ sử dụng một phông chữ tùy chỉnh có tên là Rubik từ thư viện Phông chữ của Google để tạo kiểu cho thanh tìm kiếm. Tải phông chữ bằng cách thêm mã được đánh dấu dưới comment Load Rubik font :

search-bar.html
... <!-- Load Rubik font -->     <link href="https://fonts.googleapis.com/css?family=Rubik" rel="stylesheet"> ... 

Tiếp theo, thêm CSS tùy chỉnh vào trang dưới comment Add Custom inline CSS . Điều này sẽ đảm bảo các tiêu đề, thanh tìm kiếm và kết quả trên trang dễ đọc và dễ sử dụng.

search-bar.html
... <!-- Add Custom inline CSS -->     <style>       body {         background-color: #f5f5f5;         font-family: "Rubik", sans-serif;       }        .search-container {         margin-top: 50px;       }       .search-container .search-heading {         display: block;         margin-bottom: 50px;       }       .search-container input,       .search-container input:focus {         padding: 16px 16px 16px;         border: none;         background: rgb(255, 255, 255);         box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1) !important;       }        .results-container {         margin-top: 50px;       }       .results-container .list-group .list-group-item {         background-color: transparent;         border-top: none !important;         border-bottom: 1px solid rgba(236, 229, 229, 0.64);       }        .float-bottom-right {         position: fixed;         bottom: 20px;         left: 20px;         font-size: 20px;         font-weight: 700;         z-index: 1000;       }       .float-bottom-right .info-container .card {         display: none;       }       .float-bottom-right .info-container:hover .card,       .float-bottom-right .info-container .card:hover {         display: block;       }     </style> ... 

Đến đây bạn đã có tất cả các kiểu, hãy thêm HTML sẽ xác định tiêu đề và thanh nhập liệu bên dưới chú thích của Page Header and Search Bar :

search-bar.html
... <!-- Content --> <!-- Page Header and Search Bar -->       <div class="container search-container">         <div class="row justify-content-center">           <div class="col-md-auto">             <div class="search-heading">               <h2>Search for Materials Published by Author Name</h2>               <p class="text-right">powered by <a href="https://www.crossref.org/">Crossref</a></p>             </div>           </div>         </div>         <div class="row justify-content-center">           <div class="col-sm-8">             <div class="input-group input-group-md">               <input id="search-input" type="text" class="form-control" placeholder="eg. Richard" aria-label="eg. Richard" autofocus>             </div>           </div>         </div>       </div> ... 

Điều này sử dụng hệ thống lưới từ Bootstrap để cấu trúc tiêu đề trang và thanh tìm kiếm. Bạn đã chỉ định một số nhận dạng search-input tìm kiếm cho thanh tìm kiếm, mà bạn sẽ sử dụng để liên kết với một trình nghe ở phần sau của hướng dẫn.

Tiếp theo, bạn sẽ tạo một vị trí để hiển thị kết quả tìm kiếm. Trong comment Results , hãy tạo một div với mã định response-list để thêm kết quả vào phần sau của hướng dẫn:

search-bar.html
... <!-- Results -->       <div class="container results-container">         <div class="row justify-content-center">           <div class="col-sm-8">             <ul id="response-list" class="list-group list-group-flush"></ul>           </div>         </div>       </div> ... 

Đến đây, file search-bar.html sẽ giống như sau:

search-bar.html
<!DOCTYPE html> <html>    <head>     <title>RxJS Tutorial</title>     <!-- Load CSS -->     <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.2.1/css/bootstrap.min.css" integrity="sha384-GJzZqFGwb1QTTN6wy59ffF1BuGJpLSa9DkKMp0DgiMDm4iYMj70gZWKYbI706tWS" crossorigin="anonymous">     <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.7.0/animate.min.css" />      <!-- Load Rubik font -->     <link href="https://fonts.googleapis.com/css?family=Rubik" rel="stylesheet">      <!-- Add Custom inline CSS -->     <style>       body {         background-color: #f5f5f5;         font-family: "Rubik", sans-serif;       }        .search-container {         margin-top: 50px;       }       .search-container .search-heading {         display: block;         margin-bottom: 50px;       }       .search-container input,       .search-container input:focus {         padding: 16px 16px 16px;         border: none;         background: rgb(255, 255, 255);         box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2), 0 25px 50px 0 rgba(0, 0, 0, 0.1) !important;       }        .results-container {         margin-top: 50px;       }       .results-container .list-group .list-group-item {         background-color: transparent;         border-top: none !important;         border-bottom: 1px solid rgba(236, 229, 229, 0.64);       }        .float-bottom-right {         position: fixed;         bottom: 20px;         left: 20px;         font-size: 20px;         font-weight: 700;         z-index: 1000;       }       .float-bottom-right .info-container .card {         display: none;       }       .float-bottom-right .info-container:hover .card,       .float-bottom-right .info-container .card:hover {         display: block;       }     </style>   </head>    <body>       <!-- Content -->       <!-- Page Header and Search Bar -->       <div class="container search-container">         <div class="row justify-content-center">           <div class="col-md-auto">             <div class="search-heading">               <h2>Search for Materials Published by Author Name</h2>               <p class="text-right">powered by <a href="https://www.crossref.org/">Crossref</a></p>             </div>           </div>         </div>         <div class="row justify-content-center">           <div class="col-sm-8">             <div class="input-group input-group-md">               <input id="search-input" type="text" class="form-control" placeholder="eg. Richard" aria-label="eg. Richard" autofocus>             </div>           </div>         </div>       </div>        <!-- Results -->       <div class="container results-container">         <div class="row justify-content-center">           <div class="col-sm-8">             <ul id="response-list" class="list-group list-group-flush"></ul>           </div>         </div>       </div>        <!-- Load RxJS -->        <!-- Add custom inline JavaScript -->       <script>        </script>   </body>  </html> 

Trong bước này, bạn đã đặt ra cấu trúc cơ bản cho thanh tìm kiếm của bạn với HTML và CSS. Trong bước tiếp theo, bạn sẽ viết một hàm JavaScript chấp nhận các cụm từ tìm kiếm và trả về kết quả.

Bước 2 - Viết JavaScript

Đến đây bạn đã định dạng thanh tìm kiếm, bạn đã sẵn sàng viết mã JavaScript sẽ đóng role nền tảng cho mã RxJS mà bạn sẽ viết sau trong hướng dẫn này. Mã này sẽ hoạt động với RxJS để chấp nhận các cụm từ tìm kiếm và trả về kết quả.

Vì bạn sẽ không cần các chức năng mà Bootstrap và JavaScript cung cấp trong hướng dẫn này, bạn sẽ không tải chúng. Tuy nhiên, bạn sẽ sử dụng RxJS. Tải thư viện RxJS bằng cách thêm phần sau vào phần Load RxJS comment :

search-bar.html
... <!-- Load RxJS -->     <script src="https://unpkg.com/@reactivex/rxjs@5.0.3/dist/global/Rx.js"></script> ... 

Đến đây bạn sẽ lưu trữ các tham chiếu của div từ HTML mà kết quả sẽ được thêm vào. Thêm mã JavaScript được đánh dấu trong <script> dưới comment Add custom inline JavaScript :

search-bar.html
... <!-- Add custom inline JavaScript --> <script>         const output = document.getElementById("response-list");  </script> ... 

Tiếp theo, thêm mã để chuyển đổi phản hồi JSON từ API thành các phần tử HTML để hiển thị trên trang. Mã này trước tiên sẽ xóa nội dung của thanh tìm kiếm và sau đó đặt độ trễ cho hoạt ảnh kết quả tìm kiếm.

Thêm chức năng được đánh dấu giữa các <script> :

search-bar.html
... <!-- Add custom inline JavaScript --> <script>     const output = document.getElementById("response-list");          function showResults(resp) {         var items = resp['message']['items']         output.innerHTML = "";         animationDelay = 0;         if (items.length == 0) {           output.innerHTML = "Could not find any :(";         } else {           items.forEach(item => {             resultItem = `             <div class="list-group-item animated fadeInUp" style="animation-delay: ${animationDelay}s;">               <div class="d-flex w-100 justify-content-between"> <^>                <h5 class="mb-1">${(item['title'] && item['title'][0]) || "&lt;Title not available&gt;"}</h5>               </div>               <p class="mb-1">${(item['container-title'] && item['container-title'][0]) || ""}</p>               <small class="text-muted"><a href="${item['URL']}" target="_blank">${item['URL']}</a></small>               <div>                  <p class="badge badge-primary badge-pill">${item['publisher'] || ''}</p>                 <p class="badge badge-primary badge-pill">${item['type'] || ''}</p>               </div>             </div>             `;             output.insertAdjacentHTML("beforeend", resultItem);             animationDelay += 0.1;             });         }       }  </script> ... 

Khối mã bắt đầu bằng if là một vòng lặp có điều kiện kiểm tra kết quả tìm kiếm và hiển thị thông báo nếu không tìm thấy kết quả nào. Nếu kết quả được tìm thấy, thì vòng lặp forEach sẽ cung cấp kết quả với hình ảnh động cho user .

Trong bước này, bạn đã đặt cơ sở cho RxJS bằng cách viết ra một hàm có thể chấp nhận kết quả và trả lại nó trên trang. Trong bước tiếp theo, bạn sẽ làm cho thanh tìm kiếm hoạt động.

Bước 3 - Cài đặt trình nghe

RxJS quan tâm đến các stream dữ liệu, trong dự án này là một chuỗi các ký tự mà user nhập vào phần tử đầu vào hoặc thanh tìm kiếm. Trong bước này, bạn sẽ thêm một trình nghe trên phần tử đầu vào để lắng nghe các bản cập nhật.

Trước tiên, hãy lưu ý đến số nhận dạng search-input mà bạn đã thêm trước đó trong hướng dẫn:

search-bar.html
... <input id="search-input" type="text" class="form-control" placeholder="eg. Richard" aria-label="eg. Richard" autofocus> ... 

Tiếp theo, tạo một biến sẽ chứa các tham chiếu cho phần tử search-input . Điều này sẽ trở thành có thể Observable mà mã sẽ sử dụng để lắng nghe các sự kiện đầu vào. Observables là một tập hợp các giá trị hoặc sự kiện trong tương lai mà Observer lắng nghe và còn gọi là hàm gọi lại .

Thêm dòng được đánh dấu trong <script> bên dưới JavaScript từ bước trước:

search-bar.html
...       output.insertAdjacentHTML("beforeend", resultItem);       animationDelay += 0.1;       });   } }         let searchInput = document.getElementById("search-input"); ... 

Đến đây bạn đã thêm một biến vào đầu vào tham chiếu, bạn sẽ sử dụng toán tử fromEvent để lắng nghe các sự kiện. Điều này sẽ thêm một trình lắng nghe trên DOM , hoặc phần tử D ocument O bject M odel, cho một loại sự kiện nhất định. Phần tử DOM có thể là phần tử html , body , div hoặc img trên một trang. Trong trường hợp này, phần tử DOM của bạn là thanh tìm kiếm.

Thêm dòng được đánh dấu sau dưới biến searchInput của bạn để chuyển các tham số của bạn đến fromEvent . searchInput tử DOM searchInput của bạn là tham số đầu tiên. Tiếp theo là sự kiện input là tham số thứ hai, là loại sự kiện mà mã sẽ lắng nghe.

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input') ... 

Bây giờ trình nghe của bạn đã được cài đặt , mã của bạn sẽ nhận được thông báo khi nào có bất kỳ cập nhật nào diễn ra trên phần tử đầu vào. Trong bước tiếp theo, bạn sẽ sử dụng các toán tử để thực hiện hành động đối với các sự kiện như vậy.

Bước 4 - Thêm nhà điều hành

Operators là những hàm thuần túy với một nhiệm vụ — để thực hiện một thao tác trên dữ liệu. Trong bước này, bạn sẽ sử dụng các toán tử để thực hiện các việc khác nhau như đệm tham số input , thực hiện các yêu cầu HTTP và lọc kết quả.

Trước tiên, bạn sẽ đảm bảo kết quả cập nhật theo thời gian thực khi user nhập truy vấn. Để làm điều này, bạn sẽ sử dụng sự kiện đầu vào DOM từ bước trước. Sự kiện đầu vào DOM chứa nhiều chi tiết khác nhau, nhưng đối với hướng dẫn này, bạn quan tâm đến các giá trị được nhập vào phần tử đích. Thêm mã sau để sử dụng toán tử pluck để lấy một đối tượng và trả về giá trị tại khóa được chỉ định:

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value') ... 

Bây giờ các sự kiện đã ở định dạng cần thiết, bạn sẽ đặt thuật ngữ tìm kiếm tối thiểu là ba ký tự. Trong nhiều trường hợp, bất kỳ thứ gì ít hơn ba ký tự sẽ không mang lại kết quả phù hợp hoặc user có thể vẫn đang nhập.

Bạn sẽ sử dụng toán tử filter để đặt mức tối thiểu. Nó sẽ truyền dữ liệu tiếp tục xuống stream nếu nó thỏa mãn điều kiện được chỉ định. Đặt điều kiện độ dài lớn hơn 2 để yêu cầu ít nhất ba ký tự.

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2) ... 

Bạn cũng sẽ đảm bảo các yêu cầu chỉ được gửi trong repository ảng thời gian 500ms để giảm tải trên server API. Để làm điều này, bạn sẽ sử dụng toán tử debounceTime để duy trì một khoảng thời gian được chỉ định tối thiểu giữa mỗi sự kiện mà nó đi qua stream . Thêm mã được đánh dấu dưới toán tử filter :

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500) ... 

Ứng dụng cũng nên bỏ qua cụm từ tìm kiếm nếu không có thay đổi nào kể từ lần gọi API cuối cùng. Điều này sẽ tối ưu hóa ứng dụng bằng cách giảm hơn nữa số lượng lệnh gọi API đã gửi.

Ví dụ: user có thể nhập super cars , xóa ký tự cuối cùng (tạo thuật ngữ super car ), sau đó thêm lại ký tự đã xóa để hoàn nguyên thuật ngữ trở lại super cars . Kết quả là, thuật ngữ không thay đổi và do đó kết quả tìm kiếm sẽ không thay đổi. Trong những trường hợp như vậy, bạn không nên thực hiện bất kỳ thao tác nào.

Bạn sẽ sử dụng distinctUntilChanged điều hành cấu hình này. Toán tử này ghi nhớ dữ liệu trước đó đã được chuyển qua stream và chỉ chuyển một dữ liệu khác nếu nó khác.

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500)         .distinctUntilChanged() ... 

Đến đây bạn đã điều chỉnh các đầu vào từ user , bạn sẽ thêm mã sẽ truy vấn API với cụm từ tìm kiếm. Để làm điều này, bạn sẽ sử dụng triển khai RxJS của AJAX . AJAX thực hiện các lệnh gọi API không đồng bộ trong nền trên một trang được tải. AJAX sẽ cho phép bạn tránh reload trang có kết quả cho các cụm từ tìm kiếm mới và cũng cập nhật kết quả trên trang bằng cách tìm nạp dữ liệu từ server .

Tiếp theo, thêm mã để sử dụng switchMap để chuỗi AJAX vào ứng dụng của bạn. Bạn cũng sẽ sử dụng map để ánh xạ đầu vào thành kết quả . Mã này sẽ áp dụng chức năng được truyền cho nó cho mọi mục được phát ra bởi một Observable .

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500)         .distinctUntilChanged()         .switchMap(searchKey => Rx.Observable.ajax(`https://api.crossref.org/works?rows=50&query.author=${searchKey}`)           .map(resp => ({               "status" : resp["status"] == 200,               "details" : resp["status"] == 200 ? resp["response"] : [],               "result_hash": Date.now()             })           )         ) ... 

Mã này chia phản hồi API thành ba phần:

  • status : Mã trạng thái HTTP do server API trả về. Mã này sẽ chỉ chấp nhận 200 phản hồi hoặc thành công.
  • details : Dữ liệu phản hồi thực tế đã nhận được. Điều này sẽ chứa các kết quả cho cụm từ tìm kiếm được truy vấn.
  • result_hash : Giá trị băm của các phản hồi do server API trả về, cho mục đích của hướng dẫn này là dấu thời gian UNIX. Đây là hàm băm của kết quả thay đổi khi kết quả thay đổi. Giá trị băm duy nhất sẽ cho phép ứng dụng xác định xem kết quả có thay đổi hay không và cần được cập nhật.

Hệ thống bị lỗi và mã của bạn nên được chuẩn bị để xử lý lỗi. Để xử lý các lỗi có thể xảy ra trong lệnh gọi API, hãy sử dụng toán tử filter để chỉ chấp nhận các phản hồi thành công:

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500)         .distinctUntilChanged()         .switchMap(searchKey => Rx.Observable.ajax(`https://api.crossref.org/works?rows=50&query.author=${searchKey}`)           .map(resp => ({               "status" : resp["status"] == 200,               "details" : resp["status"] == 200 ? resp["response"] : [],               "result_hash": Date.now()             })           )         )         .filter(resp => resp.status !== false) ... 

Tiếp theo, bạn sẽ thêm mã để chỉ cập nhật DOM nếu các thay đổi được phát hiện trong phản hồi. Cập nhật DOM có thể là một hoạt động tốn nhiều tài nguyên, vì vậy việc giảm số lượng cập nhật sẽ có tác động tích cực đến ứng dụng. Vì result_hash sẽ chỉ thay đổi khi phản hồi thay đổi, bạn sẽ sử dụng nó để triển khai chức năng này.

Để làm điều này, sử dụng distinctUntilChanged điều hành như trước đây. Mã sẽ sử dụng nó để chỉ chấp nhận thông tin nhập của user khi khóa đã thay đổi.

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500)         .distinctUntilChanged()         .switchMap(searchKey => Rx.Observable.ajax(`https://api.crossref.org/works?rows=50&query.author=${searchKey}`)           .map(resp => ({               "status" : resp["status"] == 200,               "details" : resp["status"] == 200 ? resp["response"] : [],               "result_hash": Date.now()             })           )         )         .filter(resp => resp.status !== false)         .distinctUntilChanged((a, b) => a.result_hash === b.result_hash) ... 

Bạn đã qua sử dụng các distinctUntilChanged điều hành để xem toàn bộ các dữ liệu đã thay đổi, nhưng trong trường hợp này, bạn kiểm tra xem có một phím được cập nhật trong các phản ứng. So sánh toàn bộ phản hồi sẽ tốn kém tài nguyên khi so sánh với việc xác định các thay đổi trong một khóa duy nhất. Vì hàm băm chính là đại diện cho toàn bộ phản hồi, nên nó có thể tự tin được sử dụng để xác định các thay đổi phản hồi.

Hàm chấp nhận hai đối tượng, giá trị trước đó mà nó đã thấy và giá trị mới. Ta kiểm tra hàm băm từ hai đối tượng này và trả về True khi hai giá trị này trùng với nhau, trong trường hợp đó, dữ liệu được lọc ra và không được chuyển thêm trong đường ống.

Trong bước này, bạn đã tạo một đường dẫn nhận một cụm từ tìm kiếm do user nhập vào và sau đó thực hiện các kiểm tra khác nhau đối với nó. Sau khi kiểm tra xong, nó thực hiện một cuộc gọi API và trả về phản hồi ở định dạng hiển thị kết quả cho user . Bạn đã tối ưu hóa việc sử dụng tài nguyên trên cả phía client và server bằng cách giới hạn các lệnh gọi API khi cần thiết. Trong bước tiếp theo, bạn sẽ cấu hình ứng dụng để bắt đầu lắng nghe phần tử đầu vào và chuyển kết quả cho hàm sẽ hiển thị nó trên trang.

Bước 5 - Kích hoạt mọi thứ bằng đăng ký

subscribe là toán tử cuối cùng của liên kết cho phép người quan sát thấy các sự kiện dữ liệu do Observable phát ra. Nó thực hiện ba phương pháp sau:

  • onNext : Điều này chỉ định những gì phải làm khi một sự kiện được nhận.
  • onError : Đây là trách nhiệm xử lý các lỗi. Các lệnh gọi đến onNextonCompleted sẽ không được thực hiện khi phương thức này được gọi.
  • onCompleted : Phương thức này được gọi khi onNext được gọi lần cuối cùng. Sẽ không có thêm dữ liệu nào được chuyển trong đường ống.

Chữ ký này của một người đăng ký là thứ cho phép một người đạt được thực thi lười biếng , là khả năng xác định một đường ống có thể Observable và đặt nó chuyển động chỉ khi bạn đăng ký. Bạn sẽ không sử dụng ví dụ này trong mã của bạn , nhưng phần sau cho bạn thấy cách một Observable có thể được đăng ký:

Tiếp theo, đăng ký Observable và định tuyến dữ liệu đến phương thức chịu trách nhiệm hiển thị nó trong giao diện user .

search-bar.html
...       let searchInput = document.getElementById("search-input");       Rx.Observable.fromEvent(searchInput, 'input')         .pluck('target', 'value')         .filter(searchTerm => searchTerm.length > 2)         .debounceTime(500)         .distinctUntilChanged()         .switchMap(searchKey => Rx.Observable.ajax(`https://api.crossref.org/works?rows=50&query.author=${searchKey}`)           .map(resp => ({               "status" : resp["status"] == 200,               "details" : resp["status"] == 200 ? resp["response"] : [],               "result_hash": Date.now()             })           )         )         .filter(resp => resp.status !== false)         .distinctUntilChanged((a, b) => a.result_hash === b.result_hash)         .subscribe(resp => showResults(resp.details)); ... 

Lưu file sau khi thực hiện những thay đổi này.

Đến đây bạn đã hoàn thành việc viết mã, bạn đã sẵn sàng để xem và kiểm tra thanh tìm kiếm của bạn . Bấm đúp vào file search-bar.html để mở nó trong trình duyệt web . Nếu mã được nhập chính xác, bạn sẽ thấy thanh tìm kiếm của bạn .

Thanh tìm kiếm đã hoàn thành

Nhập nội dung vào thanh tìm kiếm của bạn để kiểm tra.

Một gif nội dung được nhập vào thanh tìm kiếm, hiển thị rằng hai ký tự sẽ không trả lại bất kỳ kết quả nào.

Trong bước này, bạn đã đăng ký Observable để kích hoạt mã của bạn . Đến đây bạn có một ứng dụng thanh tìm kiếm cách điệu và hoạt động.

Kết luận

Trong hướng dẫn này, bạn đã tạo một thanh tìm kiếm giàu tính năng với RxJS, CSS và HTML cung cấp kết quả theo thời gian thực cho user . Thanh tìm kiếm yêu cầu tối thiểu ba ký tự, cập nhật tự động và được tối ưu hóa cho cả client và server API.

Điều có thể được coi là một tập hợp các yêu cầu phức tạp được tạo ra với 18 dòng mã RxJS. Mã không chỉ thân thiện với người đọc mà còn sạch hơn nhiều so với việc triển khai JavaScript độc lập. Điều này nghĩa là mã của bạn sẽ dễ hiểu, cập nhật và bảo trì hơn trong tương lai.

Để đọc thêm về cách sử dụng RxJS, hãy xem tài liệu API chính thức .


Tags:

Các tin liên quan