Berikan opsi untuk impor modul ES6

144

Apakah mungkin untuk meneruskan opsi ke impor ES6?

Bagaimana Anda menerjemahkan ini:

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

ke ES6?

Fabrizio Giordano
sumber
Tidak yakin Anda bisa, ada API pemuat modul, atau setidaknya ada pada suatu waktu, yang menggunakan sesuatu seperti System.import(module), tidak yakin apakah itu memungkinkan argumen atau tidak, seseorang yang tahu lebih banyak tentang ES6 mungkin melakukannya?
adeneo
Ada solusi yang diusulkan untuk ini, yang sudah ada implementasi di node.js (melalui plugin) dan webpack: 2ality.com/2017/01/import-operator.html
Matt Browne

Jawaban:

104

Tidak ada cara untuk melakukan ini dengan satu importpernyataan, itu tidak memungkinkan untuk doa.

Jadi Anda tidak akan menyebutnya secara langsung, tetapi pada dasarnya Anda dapat melakukan hal yang sama seperti yang biasa dilakukan oleh ekspor default:

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

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

Atau, jika Anda menggunakan pemuat modul yang mendukung janji monadik , Anda mungkin dapat melakukan sesuatu seperti

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

Dengan importoperator baru itu mungkin

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

atau

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

namun Anda mungkin tidak ingin impor dinamis tetapi impor statis.

Bergi
sumber
7
Terima kasih, saya berharap ada sesuatu seperti import x from 'module' use someoptions;sintaksis
Fabrizio Giordano
1
@ Fabrizio: Jika Anda memikirkannya lebih jauh, itu tidak akan sangat membantu. Ini hanya akan berfungsi jika modul mengekspor fungsi dan mungkin seharusnya tidak diizinkan jika kita telah menamai impor (yaitu import {x, y} from 'module'). Lalu apa yang seharusnya sintaks jika saya ingin melewati beberapa argumen? Atau sebarkan array argumen? Ini adalah kasus penggunaan yang sempit dan pada dasarnya Anda mencoba menambahkan sintaks yang berbeda untuk panggilan fungsi, tetapi kami sudah memiliki panggilan fungsi yang memungkinkan kami untuk menangani semua kasus lainnya.
Felix Kling
3
@ Feliksling Saya sepenuhnya setuju dengan Anda. Saya mengonversi webapp express lama dan saya temui var session = require('express-session'); var RedisStore = require('connect-redis')(session);saya hanya ingin tahu apakah ada solusi satu baris. Saya benar-benar dapat bertahan hidup dengan membagi tugas RedisStore menjadi 2 baris :)
Fabrizio Giordano
@FabrizioGiordano: Saya bisa membayangkan sesuatu seperti import {default(someoptions) as x} from 'module'di ES7, jika memang ada kebutuhan untuk ini.
Bergi
2
Untuk session/ connect-rediscontoh, saya telah membayangkan sintaks seperti ini: import session from 'express-session'); import RedisStore(session) from 'connect-redis'.
Jeff Handley
24

Konsep

Inilah solusi saya menggunakan ES6

Sangat sesuai dengan respons @ Bergi, ini adalah "templat" yang saya gunakan ketika membuat impor yang memerlukan parameter yang diloloskan untuk classdeklarasi. Ini digunakan pada kerangka isomorfik yang saya tulis, sehingga akan bekerja dengan transpiler di browser dan di node.js (saya gunakan Babeldengan 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();

Di atas akan ditampilkan foodalam konsol

EDIT

Contoh Dunia Nyata

Sebagai contoh dunia nyata, saya menggunakan ini untuk lulus dalam namespace untuk mengakses kelas dan instance lain dalam suatu kerangka kerja. Karena kita hanya membuat fungsi dan meneruskan objek sebagai argumen, kita dapat menggunakannya dengan suka suka deklarasi kelas:

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

Impornya sedikit lebih rumit dan automagicaldalam kasus saya mengingat bahwa ini adalah keseluruhan kerangka kerja, tetapi pada dasarnya inilah yang terjadi:

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

Saya harap ini membantu!

Memutar
sumber
Karena semua modul yang Anda impor adalah kelas, mengapa tidak melewatkan parameter saat membuat instance kelas?
jasonzhao
1
@jasonzhao Hal terpenting yang perlu diperhatikan di sini adalah bahwa kelas MyViewmemperluas item-item tertentu yang tersedia di namespace framework. Meskipun sangat mungkin untuk hanya meneruskannya sebagai parameter ke kelas, itu juga tergantung pada kapan dan di mana kelas dipakai; portabilitas kemudian terpengaruh. Dalam praktiknya, kelas-kelas ini dapat diserahkan ke kerangka kerja lain yang mungkin membuat mereka berbeda (misalnya, komponen kustom Bereaksi). Ketika kelas menemukan dirinya di luar lingkup kerangka kerja, itu masih dapat mempertahankan akses ke kerangka kerja ketika dipakai karena metodologi ini.
Putar
@Swivel Tolong bantu saya butuh bantuan dengan masalah serupa: stackoverflow.com/questions/55214957/…
TSR
12

Membangun jawaban @ Bergi untuk menggunakan modul debug menggunakan es6 adalah sebagai berikut

// 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!');
mummybot
sumber
4

Saya yakin Anda bisa menggunakan modul loader ES6. http://babeljs.io/docs/learn-es6/

System.import("lib/math").then(function(m) {
  m(youroptionshere);
});
pengguna895715
sumber
3
Tapi di mana hasil m(youroptionshere)akhirnya? Saya kira Anda bisa menulis System.import('lib/math').then(m => m(options)).then(module => { /* code using module here */})... tetapi tidak terlalu jelas.
Stijn de Witt
2
Wow saya tidak percaya tidak ada cara yang elegan untuk melakukan ini di E6. Itulah cara saya menulis modul.
Robert Moskal
3

Anda hanya perlu menambahkan 2 baris ini.

import xModule from 'module';
const x = xModule('someOptions');
Mansi Teharia
sumber
1
Itu hanya meneruskan parameter ke fungsi yang telah Anda impor dan panggil. Ini tidak meneruskan opsi apa pun ke modul tempat Anda mengimpornya . xModulemenyesatkan di sini. Apa yang sebenarnya Anda miliki adalah import func from 'module'; func('someOptions');.
Dan Dascalescu
1

Saya telah mendarat di utas ini mencari yang agak mirip dan ingin mengusulkan semacam solusi, setidaknya untuk beberapa kasus (tapi lihat Catatan di bawah).

Gunakan kasing

Saya memiliki modul, yang menjalankan beberapa logika instantiation segera setelah memuat. Saya tidak suka menyebut init logic ini di luar modul (yang sama dengan panggilan new SomeClass(p1, p2)atau new ((p1, p2) => class SomeClass { ... p1 ... p2 ... })dan sejenisnya).

Saya suka bahwa logika init ini akan berjalan sekali, semacam aliran instantiasi tunggal, tetapi sekali per beberapa konteks parametrized tertentu.

Contoh

service.js memiliki ruang lingkup yang sangat mendasar:

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

Modul A melakukan:

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

Modul B melakukan:

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

Sejauh ini bagus: layanan tersedia untuk kedua modul tetapi diinisialisasi hanya sekali.

Masalah

Bagaimana membuatnya berjalan sebagai contoh lain dan init itu sendiri sekali lagi dalam konteks lain, katakanlah di Modul C?

Larutan?

Inilah yang saya pikirkan: gunakan parameter kueri. Dalam layanan kami akan menambahkan yang berikut:

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

Modul C akan melakukan:

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

modul akan diimpor kembali, itu logika init dasar akan berjalan dan kita akan lihat di konsol:

initialized in context special

Catatan: Saya sendiri menyarankan untuk TIDAK berlatih pendekatan ini banyak, tetapi meninggalkannya sebagai pilihan terakhir. Mengapa? Modul yang diimpor lebih dari satu kali lebih merupakan pengecualian daripada aturan, jadi itu adalah perilaku yang tidak terduga dan dengan demikian dapat membingungkan konsumen atau bahkan menghancurkan paradigma 'singleton' sendiri, jika ada.

GullerYA
sumber
0

Inilah pendapat saya tentang pertanyaan ini menggunakan modul debug sebagai contoh;

Pada halaman npm modul ini, Anda memiliki ini:

var debug = wajib ('debug') ('http')

Pada baris di atas, sebuah string diteruskan ke modul yang diimpor, untuk membangun. Inilah cara Anda melakukan hal yang sama di ES6


import {debug as Debug} dari 'debug' const debug = Debug ('http');


Semoga ini bisa membantu seseorang di luar sana.

Akinwale Folorunsho Habib
sumber
Mengapa memposting jawaban yang menduplikasi jawaban yang sudah diposting ?
Dan Dascalescu
1
Salahku. Tidak pernah melihat pos yang disebutkan. Hanya melihat pertanyaan dan menusuknya. Terima kasih telah menyampaikannya kepada saya.
Akinwale Folorunsho Habib
Sama-sama. Anda juga dapat menghapus jawaban duplikat jika mau.
Dan Dascalescu