web-dev-qa-db-fra.com

Options de passage aux importations de modules ES6

Est-il possible de passer des options aux importations ES6?

Comment traduisez-vous ceci:

var x = require('module')(someoptions);

à ES6?

129
Fabrizio Giordano

Il n'y a aucun moyen de faire cela avec une seule instruction import, elle ne permet pas les invocations.

Donc, vous ne l'appelleriez pas directement, mais vous pouvez fondamentalement faire la même chose que ce que fait commonjs avec les exportations par défaut:

// module.js
export default function(options) {
    return {
        // actual module
    }
}

// main.js
import m from 'module';
var x = m(someoptions);

Si vous utilisez un chargeur de module prenant en charge les promesses monadique , vous pourrez peut-être faire quelque chose comme:

System.import('module').ap(someoptions).then(function(x) {
    …
});

Avec le nouvel opérateur import , il pourrait devenir

const promise = import('module').then(m => m(someoptions));

ou

const x = (await import('module'))(someoptions)

cependant, vous ne voulez probablement pas une importation dynamique, mais statique.

93
Bergi

Concept

Voici ma solution en utilisant ES6

Très en ligne avec la réponse de @ Bergi, il s'agit du "modèle" que j'utilise lors de la création d'importations nécessitant la transmission de paramètres pour les déclarations class. Ceci est utilisé sur un framework isomorphe que j'écris, donc fonctionnera avec un transpiler dans le navigateur et dans node.js (j'utilise Babel avec Webpack):

./ MyClass.js

export default (Param1, Param2) => class MyClass {
    constructor(){
        console.log( Param1 );
    }
}

./ main.js

import MyClassFactory from './MyClass.js';

let MyClass = MyClassFactory('foo', 'bar');

let myInstance = new MyClass();

Ce qui précède affichera foo dans une console

EDIT

Exemple du monde réel

Pour un exemple concret, j'utilise ceci pour transmettre un espace de noms permettant d'accéder à d'autres classes et instances au sein d'une structure. Comme nous créons simplement une fonction et passons l'objet en tant qu'argument, nous pouvons l'utiliser avec notre déclaration de classe likeso:

export default (UIFramework) => class MyView extends UIFramework.Type.View {
    getModels() {
        // ...
        UIFramework.Models.getModelsForView( this._models );
        // ...
    }
}

L'importation est un peu plus compliquée et automagical dans mon cas étant donné qu'il s'agit d'un cadre complet, mais c'est essentiellement ce qui se passe:

// ...
getView( viewName ){
    //...
    const ViewFactory = require(viewFileLoc);
    const View = ViewFactory(this);
    return new View();
}
// ...

J'espère que ça aide!

20
Swivel

Construire sur @ Bergi réponse pour utiliser le module de débogage en utilisant es6 serait le suivant

// original
var debug = require('debug')('http');

// ES6
import * as Debug from 'debug';
const debug = Debug('http');

// Use in your code as normal
debug('Hello World!');
9
mummybot

Je pense que vous pouvez utiliser les chargeurs de modules es6. http://babeljs.io/docs/learn-es6/

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});
4
user895715

Vous avez juste besoin d'ajouter ces 2 lignes.

import xModule from 'module';
const x = xModule('someOptions');
2
Mansi Teharia

J'ai atterri sur ce fil en recherchant quelque chose de similaire et aimerais proposer une meilleure solution, à mon humble avis, du moins dans certains cas, une solution (ou savoir pourquoi ce n'est pas le cas).

Cas d'utilisation

J'ai un module qui exécute une logique d'instanciation immédiatement après le chargement. Je ne pas aime appeler cette logique d’initialisation en dehors du module (ce qui revient à appeler new SomeClass(p1, p2) ou new ((p1, p2) => class SomeClass { ... p1 ... p2 ... }) et de la même façon).

J'aime que cette logique d'initialisation s'exécute une fois, une sorte de flux d'instanciation singulier, mais une fois par contexte paramétré spécifique.

Exemple

service.js a pour but fondamental:

let context = null;                  // meanwhile i'm just leaving this as is
console.log('initialized in context ' + (context ? context : 'root'));

Le module A fait:

import * as S from 'service.js';     // console has now "initialized in context root"

Le module B fait:

import * as S from 'service.js';     // console stays unchanged! module's script runs only once

Jusqu'ici tout va bien: le service est disponible pour les deux modules mais n'a été initialisé qu'une fois.

Problème

Comment le faire fonctionner comme une autre instance et s'initier à nouveau dans un autre contexte, par exemple dans le module C?

Solution?

Voici ce à quoi je pense: utiliser des paramètres de requête. Dans le service, nous ajoutons ce qui suit:

let context = new URL(import.meta.url).searchParams.get('context');

Le module C ferait:

import * as S from 'service.js?context=special';

le module sera réimporté, sa logique d’initialisation de base s’exécutera et nous verrons dans la console:

initialized in context special

0
GullerYA