Klien HTTP deklaratif berbasis Axios untuk browser dan node.js.
Ditulis oleh seorang programmer java yang terbiasa dengan klien HTTP deklaratif.
Tujuannya adalah menyediakan klien http yang sederhana dan ringkas di semua lingkungan javascript/typescript, (sebenarnya lingkungan es6) ( Belum! )
Karena babel-plugin-transform-decorators-legacy belum mendukung dekorator parameter, sehingga RetrofitJs hanya bekerja di lingkungan TypeScript untuk saat ini.
Kutip proposalnya di sini:
Anda dapat mendekorasi seluruh kelas, serta deklarasi bidang, pengambil, penyetel, dan metode. Argumen dan deklarasi fungsi tidak dapat dihias. -- dari dekorator proposal
dan juga seseorang mengajukan permintaan ini -> Dekorator Parameter?
Sekarang, mari kita fokus pada mendeklarasikan antarmuka http sendiri daripada detail http, seperti yang dilakukan Retrofit, tulis lebih sedikit, lakukan lebih banyak.
Terakhir, terima kasih kepada semua orang yang menulis atau memperbarui Axios (klien http javascript) dan Retrofit (klien java http), itu adalah proyek yang luar biasa, ini mengajari saya banyak hal.
Program ini tidak dapat bekerja pada IE8/9/10/11 dan lingkungan lain (biasanya browser) yang tidak mendukung es6 secara asli, karena bergantung pada objek Proxy (es6) dan fitur Decorator (tahap 2).
Dengan kata lain, RetrofitJs dapat bekerja pada lingkungan apa pun yang mendukung es6 secara asli.
Tentang objek Proxy , saya tidak dapat menemukan polyFill apa pun yang didukung. Namun untuk Decorator , Anda dapat menggunakannya dengan sesuatu yang mendukung babel seperti babel-plugin-transform-decorators-legacy .
Menggunakan npm:
npm install retrofitjs
// This is typescript demo, also javascript demo( it is if you remove all type define )
// In the first step, you must create your retrofit object.
let client = Retrofit . getBuilder ( )
. setConfig < RetrofitConfig > ( { /** config, you can use retrofit config or axios config */ } )
. addInterceptor ( /** your interceptor */ )
. setErrorHandler ( /** define your error handler */ )
. build ( ) ;
// This is the part of define any interface what you need.
@ HTTP ( "/testing" )
@ Headers ( [ "Cache-Control: no-store" ] )
class TestingClient {
@ GET ( "/demo1/:callByWho/:when" )
public demo1 ( @ Path ( "callByWho" ) name : string , @ Path ( "when" ) time : number ) : RetrofitPromise < string > & void {
}
@ POST ( "/demo2/:file" )
public demo2 ( @ Path ( "file" ) file : string , @ Header ( "cookie" ) val : string , @ Config localConfig : AxiosConfig ) : RetrofitPromise < string > & void {
}
}
// The final step, create your client.
export let testingClient = client . create ( TestingClient ) ;
// When you are calling this method, it is a http call actually.
testingClient . demo1 ( "itfinally" , Date . now ( ) ) . then ( response => {
// any code
} ) . catch ( reason => {
// any code
} ) ;
// And you can also get axios instance.
let axios : AxiosInstance = client . getEngine ( ) ; Seperti Retrofit, RetrofitJs juga diimplementasikan melalui rantai interseptor. Semua pencegat diurutkan berdasarkan bidang order , dan diurutkan dari yang terbesar ke yang terkecil .
// This is a interceptor interface
export interface Interceptor {
order : number ;
init ( config : RetrofitConfig ) : void ;
intercept ( chain : Chain ) : Promise < ResponseInterface < any > >
} Hati-hati, pencegat RealCall adalah pencegat terakhir, dan memang demikian.
Ini adalah pencegat default, nilai bidang order adalah nol. RetrofitJs menggunakannya untuk mengirim semua permintaan http melalui objek Axios.
Untuk menghindari konflik, jumlah kolom pesanan kurang dari 256 (tidak termasuk 256) dicadangkan.
Anda dapat dengan mudah mengimplementasikan pencegat Anda sendiri, seperti ini.
class MyInterceptor implement Interceptor {
public order : number = 256 ;
public init ( config : RetrofitConfig ) : void {
// Initializing your interceptor
}
public intercept ( chain : Chain ) : Promise < ResponseInterface < any > > {
// Your code
return chain . proceed ( chain . request ( ) ) ;
}
} Perhatikan chain.proceed( chain.request() ) , kode ini memutuskan apakah permintaan akan dilanjutkan.
Jika Anda menelepon dengan chain.proceed , permintaan saat ini akan ditransfer ke pencegat berikutnya. Jika tidak, pencegat lainnya tidak akan aktif. Dan seluruh proses akan dihentikan dan penangan kesalahan aktif jika ada kesalahan yang muncul dari rantai pencegat.
Faktanya, plugin adalah pencegat, Anda dapat menulis plugin Anda sendiri untuk RetrofitJs.
Retrofit.use( new MyInterceptor implements Interceptor {
public order: number = 20;
public init( config: RetrofitConfig ): void {
}
public intercept( chain: Chain ): Promise<ResponseInterface<any>> {
}
} );
Ini akan menambahkan semua interseptor ke Retrofit saat Anda membuat sebuah instance.
Tidak ada batasan untuk bidang pemesanan plugin. Faktanya, ada nomor yang dicadangkan untuk plugin dan pencegat default.
Dan ini semua adalah pencegat default:
| pencegat | memesan |
|---|---|
| Panggilan Nyata | 0 |
| Coba lagiRequestInterceptor | 1 |
| Pencegat Logger | 5 |
Pencegat ini dinonaktifkan secara default, ia akan mencoba lagi dengan waktu acak ketika permintaan idempoten memiliki anomali jaringan. seperti batas waktu koneksi saat Anda mengirim permintaan 'GET'.
Jika Anda ingin menggunakannya, Anda harus menyetel maxTry dan timeout di RetrofitConfig .
Anda dapat mengatur di RetrofitConfig :
{
"maxTry": "number",
"retryCondition": "RetryCondition"
}
RetryCondition adalah sebuah antarmuka, pencegat akan mencoba mengirim permintaan lagi jika RetryCondition.handler mengembalikan nilai true.
Pencegat ini dinonaktifkan secara default, ia akan mencatat semua permintaan/respons (atau kesalahan) dan mencetaknya di konsol.
Anda dapat mengatur di RetrofitConfig :
{
"debug": "boolean"
}
Anda dapat dengan mudah membatalkan permintaan.
let tick = testingClient . demo1 ( ... args ) ;
// Careful the different between micro task and macro task
setTimeout ( ( ) => tick . cancel ( "your message" ) , 3000 ) ; Hati-hati, cancel api adalah metode objek RetrofitPromise , Anda tidak dapat memanggil dengan objek janji lainnya, ini contohnya:
// It is wrong.
tick . then ( ( ) => { ... you code } ) . cancel ( "message" ) ; Saat Anda membatalkan permintaan, itu akan memunculkan RequestCancelException , Anda dapat menangani atau mengabaikannya di penangan kesalahan.
Jika Anda ingin menangani semua pengecualian secara seragam, cukup terapkan ErrorHandler .
class MyErrorHandler implement ErrorHandler {
public handler ( realReason : any , exception : Exception ) : void {
// your code
}
} realReason adalah parameter yang diberikan oleh aksio, dan exception adalah turunan dari Exception , Anda dapat dengan mudah menyeragamkan proses semua pengecualian.
Ini semua pengecualian:
| pengecualian | keterangan |
|---|---|
| PermintaanBatalPengecualian | Pembatalan Pengguna |
| HubungkanPengecualian | Sinyal ECONNREFUSED diaktifkan |
| SocketException | Sinyal ECONNRESET diaktifkan |
| Pengecualian Waktu Habis Permintaan | Sinyal ECONNABORTED atau ETIMEDOUT diaktifkan |
| Pengecualian IO | sisa situasi yang tidak diketahui |
Meskipun error handler dapat menangkap semua pengecualian, namun bukan berarti Promise.catch tidak akan aktif. Faktanya, hal ini diperlukan untuk menghentikan proses normal ketika pengecualian telah dilempar.
class MyErrorHandler implement ErrorHandler {
public handler ( realReason : any , exception : Exception ) : void {
// Your code
}
}
testingClient . demo1 ( ... args ) . then ( response => {
// Normal business process
} ) . catch ( reason => {
// Active after error handler call
} ) ; Dalam tanda metode tunggal, tidak dapat menghiasi parameter tunggal dengan multi-dekorator.
// It is wrong!
public demo1 < T > ( @ Field ( "key1" ) @ Header ( "header1" ) val1 : any ) : RetrofitPromise < T > & void {
} Jika Anda ingin membuat kueri url seperti https://127.0.0.1/demo?key1=val1&key2=val2 , lakukan saja sebagai berikut:
public demo1 < T > ( @ Query ( "key1" ) val1 : any , @ QueryMap map1 : object ) : RetrofitPromise < T > & void {
}@Query mendeklarasikan entri nilai kunci kueri.@QueryMap mendeklarasikan entri multi-nilai-kunci kueri.Mudah untuk mengirimkan formulir.
@ FormUrlEncoded
public demo1 < T > ( @ Field ( "key1" ) val1 : any , @ FieldMap map1 : object ) : RetrofitPromise < T > & void {
} @Field dan @FieldMap hanya efektif jika metode telah dideklarasikan oleh @FormUrlEncoded .
@FormUrlEncoded menyatakan ini adalah formulir.@Field mendeklarasikan entri nilai kunci formulir.@FieldMap mendeklarasikan formulir entri nilai multi-kunci. Jika Anda ingin meminta dengan json body, gunakan @Body untuk menghias parameter.
public demo1 < T > ( @ Body myBody : object ) : RetrofitPromise < T > & void {
} @Body tidak dapat digunakan dengan @FormUrlEncoded atau @MultiPart , karena ada satu isi dalam satu permintaan. Juga @Body tidak dapat menggunakan lebih dari satu tanda metode yang sama.
// It is wrong!
public demo1 < T > ( @ Body myBody : object , @ Body otherBody : object ) : RetrofitPromise < T > & void {
} Seperti kasus di atas, parameter myBody akan diabaikan.
Jika Anda ingin mengganti konfigurasi, gunakan @Config untuk menghias parameter.
public demo1 < T > ( @ Config config : RetrofitRequest ) : RetrofitPromise < T > & void {
}Ini akan menimpa pengaturan dekorator (tetapi tidak termasuk konfigurasi global) dengan bidang yang memuat parameter konfigurasi.
Konfigurasi dinamis hanya efektif dalam permintaan, tetapi tidak untuk konfigurasi pencegat, karena pencegat diinisialisasi saat Anda memanggil Retrofit.getBuilder().build() dan hanya diinisialisasi satu kali.
Anda dapat dengan mudah mengunggah file dengan RetrofitJs, sebagai berikut:
@ MultiPart
@ PUT ( "/upload" )
public upload ( @ Part ( "file" ) file : any , @ PartMap anything : any ) : RetrofitPromise < void > & void {
}Ini cara browsernya:
// document.getElementById( "file" ) is a input tag
client . upload ( document . getElementById ( "file" ) . files [ 0 ] ) ;Dan ini cara simpulnya:
// create a file read stream as parameter, done.
client . upload ( fs . createReadStream ( "your file path" ) ) ; Seperti pengiriman formulir, @Part dan @PartMap juga hanya efektif jika metode telah dideklarasikan oleh @MultiPart .
@MultiPart menyatakan ini adalah formulir.@Part mendeklarasikan entri nilai kunci formulir.@PartMap mendeklarasikan formulir entri nilai multi-kunci.Anda juga harus berhati-hati dengan pengaturan ukuran file maksimal di server Anda. Pengunggahan selalu gagal jika ukuran file lebih besar dari batas server Anda.
Terakhir, Jangan gunakan objek Buffer sebagai parameter, saya mencoba menggunakan objek buffer untuk mengunggah, tetapi semua gagal karena objek buffer hanya memiliki data tetapi tidak ada deskripsi seperti nama file, tipe file.
Di Browser, Tidak ada cara untuk mendownload file dengan Ajax karena Ajax selalu merespons dengan data string, tetapi Anda dapat menggunakan tag iframe untuk mendownload browser aktif.
Anda dapat mengunduh file di node, sebagai berikut:
@ ResponseBody ( ResponseType . STREAM )
public demo1 ( ) : RetrofitPromise < Stream > & void {
} @ResponseBody akan memberi tahu RetrofitJ tipe apa yang harus dikembalikan.
Ini semua adalah jenis respons yang didukung:
| jenis | nilai |
|---|---|
| obyek | ResponseType.JSON ( bawaan ) |
| rangkaian | ResponseType.DOKUMENT, ResponseType.TEXT |
| Sungai kecil | Tipe Respon.STREAM |
| Penyangga | Tipe Respons.ARRAY_BUFFER |
Ini adalah bab terakhir, seperti yang Anda lihat, RetrofitJs hanya menyediakan platform, dan semua antarmuka http harus ditulis sendiri.
Anda juga dapat menulis antarmuka umum dan memperluasnya , kemudian pengumpul informasi berfungsi sebagai berikut:
Singkatnya, rantai prioritas informasi mengikuti ini: @Config > metode > kelas ini > kelas super
MIT