Pendahuluan
Merancang sistem perbankan online modern adalah tugas yang agak rumit. Pada saat yang sama, sejumlah tugas untuk mengembangkan bagian klien dari aplikasi dikaitkan dengan proses pemrosesan sejumlah besar data yang datang hampir bersamaan dari beberapa sumber informasi. Data dari sistem perbankan jarak jauh (RBS), layanan pesan instan, berbagai layanan informasi harus diterima dan diproses secara real time di sini dan sekarang. Untuk mengatasi masalah seperti ini, metode pemrograman reaktif banyak digunakan saat ini.
Istilah "pemrograman reaktif" dalam arti luas berarti organisasi aplikasi, di mana penyebaran perubahan dalam sistem terjadi sebagai hasil dari pemrosesan status aliran data. Masalah penting dengan metode ini adalah kesederhanaan penyajian arus informasi dan kemungkinan merespons kesalahan yang terjadi selama pemrosesan hasil presentasi yang tidak sinkron.
Dalam arti sempit, pemrograman UI web reaktif dapat berarti menggunakan alat pengembang yang tidak tersedia, seperti perpustakaan RxJs. Perpustakaan ini menyediakan representasi diskrit dari urutan data menggunakan objek yang dapat diobservasi, yang berfungsi sebagai sumber informasi memasuki aplikasi pada interval tertentu.
Pertimbangkan fitur menggunakan perpustakaan pada contoh merancang antarmuka web bank online untuk bisnis kecil. Saat mengembangkan UI, kami menggunakan platform Google Angular 6 dengan pustaka RxJs bawaan versi 6.
Tugas Desain UI Reaktif
Untuk pengguna, sebagian besar operasi di Internet Bank sering turun ke tiga tahap:
- memilih operasi yang diperlukan dari daftar, misalnya, membayar pinjaman atau mengisi kembali akun;
- penyelesaian sebagian dari formulir yang sesuai (perincian pembayaran diisi secara otomatis dengan nama organisasi atau nama penerima pembayaran yang dimasukkan oleh pengguna);
- konfirmasi operasi secara otomatis menggunakan pesan SMS atau tanda tangan elektronik.
Dari sudut pandang pengembang, implementasi tahapan ini mencakup solusi dari tugas-tugas berikut:
- memeriksa keadaan sistem RB, memastikan relevansi data tentang operasi dalam daftar;
- pemrosesan arus data yang tidak sinkron ketika mengisi formulir, termasuk data yang dimasukkan oleh pengguna dan diterima dari layanan pesan informasi (misalnya, TIN dan BIC bank, misalnya);
- validasi formulir yang sudah diisi;
- otomatis menyimpan data dalam bentuk.
Memeriksa status sistem RBS
Proses memperoleh data yang relevan dari sistem RB, misalnya, informasi tentang batas kredit atau status pesanan pembayaran, mencakup dua tahap:
- memeriksa status ketersediaan data;
- menerima data yang diperbarui.
Untuk memeriksa keadaan data saat ini, permintaan diajukan ke API sistem dengan periode waktu tertentu dan hingga tanggapan diterima tentang kesiapan data.
Ada beberapa kemungkinan jawaban untuk sistem RB:
- {empty: true} - data belum siap;
- data yang diperbarui dapat diterima oleh klien;
{ empty: false
Akibatnya, penerimaan data yang relevan dilakukan dalam bentuk:
const MIN_TIME = 2000; const MAX_TIME = 60000; const EXP_BASE = 1.4; request()
Mari kita menganalisis langkah demi langkah:
- Kami mengirim permintaan. permintaan ()
- Jawabannya berkembang. Expand adalah pernyataan RxJS yang secara berulang mengulang kode dalam bloknya untuk setiap peringatan berikutnya untuk Pengamatan internal dan eksternal, hingga utas mengumumkan penyelesaiannya yang berhasil. Oleh karena itu, untuk menyelesaikan streaming, perlu untuk mengembalikan Observable sedemikian sehingga tidak ada satu berikutnya - KOSONG.
- Jika tanggapan datang {kosong: true}, maka kami membuat permintaan kedua setelah penundaan waktu tertentu (delayTime). Agar tidak membebani server dengan permintaan, kami menambah interval waktu untuk ping dengan setiap permintaan baru.
- Jika selama permintaan berikutnya datang sesuatu yang lain sebagai respons, maka berhentilah melakukan ping (kembalikan KOSONG) dan kembalikan hasil dari permintaan terakhir ke pelanggan (terakhir () operator).
- Setelah menerima jawabannya, kami mengambil hasilnya dan memprosesnya. Objek formulir akan berlangganan:
{ empty: false
Bentuk reaktif
Pertimbangkan tugas merancang formulir web reaktif dari dokumen pembayaran menggunakan pustaka ReactiveForms dari kerangka kerja Angular.
Tiga kelas dasar pustaka FormControl, FormGroup, dan FormArray memungkinkan Anda untuk menggunakan deskripsi deklaratif bidang formulir, mengatur nilai awal bidang, dan menetapkan aturan validasi untuk setiap bidang:
this.myForm = new FormGroup({ name: new FormControl('', Validators.required),
Untuk formulir dengan sejumlah besar bidang, biasanya menggunakan layanan FormBuilder, yang memungkinkan Anda untuk membuatnya menggunakan kode yang lebih ringkas
this.myForm = this.fb.group({ name: ['', Validators.required], surname: '' });
Setelah membuat formulir di templat halaman pesanan pembayaran, cukup untuk menentukan tautan ke formulir MyForm, serta nama-nama nama dan nama bidangnya.
<form [formGroup]="myForm"> <label>Name: <input formControlName="name"> </label> <label>Surname: <input formControlName="surname"> </label> </form>
Desain yang dihasilkan memungkinkan Anda untuk membuat dan melacak setiap aliran informasi yang melewati bidang formulir sebagai hasil dari input pengguna, dan berdasarkan pada logika bisnis aplikasi. Untuk melakukan ini, cukup berlangganan acara yang dihasilkan oleh pengamat asinkron formulir ValueChanges
this.myForm.valueChanges .subscribe(value => { …
Misalkan logika bisnis mendefinisikan persyaratan untuk secara otomatis mengisi rincian tujuan pembayaran ketika pengguna memasukkan NPWP penerima atau nama organisasi. Kode untuk memproses data yang dimasukkan oleh pengguna dalam TIN / nama organisasi akan terlihat seperti:
this.payForm.valueChanges .pipe( mergeMap(value => this.getRequisites(value))
Validasi
Validator datang dalam dua bentuk:
Kami menjumpai validator sinkron secara teratur - ini adalah fungsi yang memeriksa data yang dimasukkan saat bekerja dengan bidang. Dalam hal bentuk reaktif:
"Validator sinkron adalah fungsi yang mengambil bentuk kontrol dan mengembalikan nilai kebenaran jika ada kesalahan dan kesalahan sebaliknya."
function customValidator(control) { return isInvalid(control.value) ? { code: "mistake", message: "smth wents wrong" } : null; }
Kami akan menerapkan validator yang akan memeriksa apakah pengguna ditunjukkan dalam bentuk serangkaian dokumen, jika paspor sebelumnya ditentukan sebagai jenis dokumen identifikasi:
function requredSeria(control) { const docType = control.parent.get("docType"); let error = null; if (docType && docType.value === "passport" && !control.value) { error = { code: "wrongSeria", message: " " } } return error; }
Di sini kita juga merujuk ke formulir induk dan menggunakannya kita mendapatkan nilai dari bidang lain. Dimungkinkan untuk mengembalikan benar hanya sebagai kesalahan, tetapi dalam kasus ini diputuskan untuk melakukan sebaliknya. Anda bisa menangkap pesan kesalahan ini di bidang kesalahan kontrol atau formulir. Jika bidang memiliki beberapa validator, Anda dapat menentukan dengan tepat mana validator yang gagal menampilkan pesan kesalahan yang diinginkan atau menyesuaikan validasi bidang lain.
Validator akan ditambahkan ke formulir sebagai berikut:
this.documentForm = this.fb.group({ docType: ['', Validators.required], seria: ['', requredSeria], number: '' });
Di luar kotak, beberapa validator yang sering ditemui juga tersedia. Semuanya diwakili oleh metode statis dari kelas Validator. Ada juga metode untuk menyusun validator.
Ketidaktepatan satu bidang langsung mengarah ke ketidakabsahan seluruh formulir. Ini dapat digunakan ketika Anda perlu menonaktifkan tombol OK tertentu, jika formulir memiliki setidaknya satu bidang yang tidak valid. Kemudian semuanya turun untuk memeriksa satu syarat "myform.invalid", yang akan mengembalikan true jika formulir tidak valid.
Validator asinkron memiliki satu perbedaan - tipe nilai pengembalian. Nilai kebenaran atau kepalsuan harus diberikan dalam janji atau dalam Pengamatan.
Setiap kontrol atau setiap formulir memiliki status (mySuperForm.status), yang dapat berupa "VALID", "INVALID", "DISABLED". Karena ketika menggunakan validator asinkron, mungkin tidak jelas dalam kondisi apa formulir saat ini, ada status khusus "PENDING". Berkat kondisi ini (mySuperForm.status === "PENDING"), Anda dapat menampilkan preloader atau membuat style styling lainnya.
Simpan otomatis
Pengembangan perangkat lunak perbankan (software) melibatkan bekerja dengan berbagai dokumen standar. Sebagai contoh, ini adalah formulir aplikasi atau kuesioner, yang dapat terdiri dari puluhan bidang yang diperlukan. Saat bekerja dengan dokumen yang sangat banyak, dukungan penyimpanan otomatis diperlukan untuk kenyamanan pengguna tambahan, sehingga jika Anda kehilangan koneksi Internet atau masalah teknis lainnya, data yang dimasukkan pengguna sebelumnya tetap dalam versi konsep di server.
Berikut adalah aspek utama dari prosedur penyimpanan otomatis untuk arsitektur client-server:
- Simpan permintaan harus diproses oleh server sesuai urutan perubahan dilakukan. Jika Anda segera mengirim permintaan ke setiap perubahan, Anda tidak dapat menjamin bahwa permintaan sebelumnya tidak akan datang berikutnya dan tidak akan menimpa perubahan baru.
- Tidak perlu mengirim sejumlah besar permintaan ke server sampai pengguna selesai memasukkan, cukup dengan melakukan ini berdasarkan waktu.
- Jika beberapa perubahan telah dilakukan dengan penundaan yang relatif besar, dan permintaan untuk perubahan pertama belum dikembalikan, maka tidak perlu mengirim permintaan untuk setiap perubahan selanjutnya segera setelah kembalinya permintaan pertama. Anda hanya dapat mengambil yang terakhir, agar tidak mengirim data yang tidak relevan.
Kasing pertama dapat dengan mudah ditangani dengan menggunakan operator
concatMap . Kasus kedua akan diselesaikan tanpa masalah menggunakan
debounceTime . Logika yang ketiga dapat digambarkan sebagai:
const lastRequest$ = new BehaviorSubject(null);
Tetap di saveQueue $ untuk mengirim permintaan. Catat keberadaan operator
exaustMap alih-alih concatMap. Operator ini perlu mengabaikan semua pemberitahuan Observable eksternal sampai internal telah menyelesaikan pengamatannya ("dikompilasi"). Namun dalam kasus kami, jika selama permintaan akan ada antrian pemberitahuan baru, kami harus mengambil yang terakhir dan membuang sisanya. exaustMap akan menghapus semuanya, termasuk yang terakhir. Oleh karena itu, kami menyimpan pemberitahuan terakhir di BehaviorSubject, dan dalam berlangganan, jika permintaan yang diselesaikan saat ini berbeda dari yang terakhir, kami akan melemparkan permintaan terakhir ke dalam antrian lagi.
Perlu juga diperhatikan untuk mengabaikan kesalahan selama permintaan, diimplementasikan menggunakan
pernyataan catchError . Anda dapat menulis penanganan kesalahan yang lebih kompleks dengan pemberitahuan untuk pengguna bahwa terjadi kesalahan saat menyimpan. Tetapi intinya adalah bahwa ketika kesalahan terjadi dalam aliran, aliran tidak boleh ditutup, seperti halnya dengan kesalahan dan pemberitahuan lengkap.
Kesimpulan
Tingkat perkembangan hari ini dari teknologi pemrograman reaktif menggunakan perpustakaan RxJS memungkinkan Anda untuk membuat aplikasi klien lengkap untuk sistem perbankan online tanpa biaya tenaga kerja tambahan untuk mengatur interaksi dengan antarmuka sistem perbankan jarak jauh yang sangat banyak dimuat.
Kenalan pertama dengan RxJS dapat menakut-nakuti bahkan seorang pengembang berpengalaman yang dihadapkan dengan "seluk-beluk" perpustakaan yang menerapkan pola desain "Pengamat". Tapi, mungkin mengatasi kesulitan ini, di masa depan, RxJS akan menjadi alat yang sangat diperlukan dalam menyelesaikan masalah pemrosesan asinkron aliran data heterogen secara real time.