@teqfw / di

Beberapa suka mengendarai sepeda dan beberapa suka menemukan kembali mereka. Saya adalah salah satu dari mereka yang menemukan kembali sepeda untuk dikendarai. Beberapa tahun yang lalu saya sudah menulis di Habr tentang " sepeda " saya ini - wadah DI untuk JavaScript. Diskusi selanjutnya tentang prinsip pengoperasian kontainer DI dan perbedaannya dari " Service Locator " cukup membuat saya memahami pekerjaan " sepeda " saya sendiri dan menghasilkan tidak hanya sejumlah artikel tentang Habré ( satu , dua , tiga ) , empat ), tetapi juga sebagian besar penyelesaian " sepeda " itu sendiri.





Di bawah potongan - deskripsi pekerjaan wadah DI ( @ teqfw / di ) pada saat ini. Keterbatasan: wadah ditulis dalam JavaScript murni (ES2015 +), hanya berfungsi dengan kode ES2015 +, didekorasi dengan modul ES dengan ekstensi *.mjs



. Keuntungan: memungkinkan Anda memuat dan menggunakan modul yang sama baik di browser maupun di aplikasi nodejs tanpa transpilasi tambahan.





Dasar-dasar Kontainer DI DI

Panggilan khas ke wadah objek abstrak terlihat seperti ini:





const obj = container.get(id);
      
      



Urutan tindakan wadah:





  1. Tentukan dengan id objek seperti apa yang ingin didapatkan oleh penelepon.





  2. Periksa wadah untuk keberadaan objek yang diminta, jika objek ada di dalam wadah, kembalikan.





  3. Jika objek perlu dibuat, gunakan id untuk menentukan di mana file dengan kode sumber objek berada dan unduh sumbernya.





  4. ( ).





  5. .





  6. .





  7. ( ).





  8. .





— 5 , , .





ES-

, ES- — .., DI- ES-.





const obj = {name: 'Simple Object'};
class Clazz {
    constructor(spec) {
        this.name = 'instance from class constructor';
    }
}
function Factory(spec) {
    return {name: 'instance from factory'};
}
export {
    obj as ObjTmpl,
    Clazz as default,
    Factory,
}
      
      



, ES- (, ):





import Def from './es6.mjs';
import {Factory} from './es6.mjs';
import {ObjTmpl} from './es6.mjs';

const spec = {}; // empty specification
const instClass = new Def(spec);
const instFact = Factory(spec);
const instTmpl = Object.assign(ObjTmpl, {});
      
      



, DI-, ES-, :





  • ;





  • ;





— , , ( ) , DI- :





constructor(spec) {
    const dep = spec['depId'];
}
...
await container.get('dep1');
      
      



:





import Container from '@teqfw/di';

const container = new Container();
container.set('dep1', {name: 'first'});
container.set('dep2', {name: 'second'});

const obj = await container.get('dep1');
      
      



ES-, (, -).





@teqfw/di



:





  • : (connection



    , conf



    , i18n



    , …);





  • : (EsModuleId



    );





container.set(id, obj)



, ( ).





@teqfw/di



ES- , Module



(. “” “Javascript: ”).





, - . @teqfw/di



#



:





  • EsModuleId



    : ;





  • EsModuleId#ExportName



    : ExportName



    EsModuleId



    ;





  • EsModuleId#default



    EsModuleId#



    : default



    EsModuleId



    ;





@teqfw/di



:





class Clazz {
    constructor(spec) {}
}

function Factory(spec) {}
      
      



, (), — ( )? @teqfw/di



$



:





  • EsModuleId#ExportName



    : (, ) ExportName



    EsModuleId



    .





  • EsModuleId#ExportName$



    : , ( ), ExportName



    EsModuleId



    .





default



- ES- :





  • EsModuleId#default$







  • EsModuleId#$







  • EsModuleId$







Singleton

( ), . "" -$$



:





  • EsModuleId$



    EsModuleId#ExportName$



    : ( ) , .





  • EsModuleId$$



    EsModuleId#ExportName$$



    : .





, singleton’ — . DI- global-. - , , DI — .





@teqfw/di



:





let id1 = 'named'; // named singleton been added manually
let id2 = 'EsModId'; // ES module
let id3 = 'EsModId#'; // default export of ES module
let id4 = 'EsModId#name'; // named export of ES module
let id5 = 'EsModId$'; // singleton from default export
let id6 = 'EsModId$$'; // new instance from default export
let id7 = 'EsModId#name$'; // singleton from named export
let id8 = 'EsModId#name$$'; // new instance from named export
      
      



, , , ( ). @teqfw/di



:





constructor(spec) {
    const named = spec['namedSingleton'];
    const inst = spec['EsModId#name$$'];
    const single = spec['EsModId$'];
}
      
      



@teqfw/di



, , , , . , , .





ES-, . @teqfw/di



:





container.addSourceMapping('EsModId', './relative/path');
container.addSourceMapping('EsModId', '/absolute/path', true);
      
      



( ) , , — nodejs-. , .





, , , namespace’, _



:





EsModId_PathTo_Mod => /absolute/path/PathTo/Mod.mjs
      
      



Wadah @ teqfw / di DI memungkinkan Anda untuk menggunakan kedua modul ES itu sendiri sebagai dependensi, serta elemen individual dari ekspor modul ES, serta membuat instance objek baru atau menggunakan satu objek untuk seluruh aplikasi. Selain itu, kode yang sama dapat digunakan baik di browser maupun di aplikasi nodejs.





Kode khas untuk modul ES yang digunakan dalam @teqfw/di



:





export default class Mod {
    constructor(spec) {
        const Clazz = spec['Lib_Dep#'];
        const single = spec['Lib_Dep$'];
        const inst = spec['Lib_Dep$$'];
        // ...
    }
}
      
      



Yang biasa import



juga dapat digunakan dalam kode, tetapi dalam kasus ini kode kehilangan kemampuan untuk digunakan secara bersamaan di browser dan aplikasi nodejs, karena format impor browser tidak kompatibel dengan format nodejs.








All Articles