2016-02-21 2 views
0

Я использую Babel для компиляции некоторых ES6 JavaScript до ES5. У меня возникают некоторые проблемы с моим кодом, потому что мои модули оцениваются в неопределенном порядке.Почему порядок выполнения моих модулей отличается от ожидаемого?

Скажем, у меня есть модули:

// a.js 
class A { 
    constructor() { 
    this.prop = window.randomProperty; 
    console.log("Prop " + this.prop); 
    } 
} 

const a = new A(); 
export default a; 

Этот модуль основан на window.randomProperty, чтобы установить, прежде чем он может создать экземпляр себя.

Теперь у меня есть главный файл:

// main.js 
import "babel-polyfill"; // Not sure if this is relevant 

window.randomProperty = function() { return "hi"; }; 
console.log("randomProperty set"); 

import A from "a"; 

Выход консоли этого:

Prop undefined 
randomProperty set 

Как я могу иметь код выполнять в правильном порядке?

+0

Никогда не используйте 'class'es для одиночных игр! Никогда не экспортируйте отдельные экземпляры! Используйте простой литерал объекта. – Bergi

ответ

0

Операции импорта заправлены, поэтому импорт загружается до того, как ваш код будет выполнен. Чтобы выполнить его по своему желанию, вы должны использовать другой загрузчик модуля, например, с помощью require.

const A = require("a"); 
+0

Есть ли способ контролировать порядок выполнения? Например, что, если я поместил 'window.randomProperty =" hi ";' в модуль и добавил 'import 'the-new-module"; 'сразу после' import' babel-polyfill? '? – Max

+0

@Max В зависимости от того, в каком порядке загружены заказы на импорт, не является хорошим шаблоном проектирования в вашем приложении (imho). Ваши модули должны делать простые вещи, а не изменять глобальное состояние. – madox2

+0

Мне нужно установить 'document.domain', чтобы мои вызовы AJAX обходили CORS, когда вызовы переходят в поддомены. Я не вижу способ сделать эту работу без изменения глобального состояния. – Max

0

Ваша проблема заключается в том, где вы инстанцируете A, попробуйте сделать это в main.js. Проверьте это:

// a.js 
class A { 
    constructor() { 
    this.prop = window.randomProperty; 
    console.log("Prop " + this.prop); 
    } 
} 

// do not instantiate here 
// const a = new A(); 
export default a; 

Просто убедитесь, что вы создаете объект здесь:

// main.js 
import A from "a"; 

window.randomProperty = function() { return "hi"; }; 
console.log("randomProperty set"); 

const a = new A(); 

Причина, при импорте модуля, он будет ссылаться на какие-либо методы, которые не привязаны к функции или определение класса.

Надеюсь, это поможет!

+0

"* при импорте модуля он будет вызывать любые методы, которые не привязаны к функции или определению класса *" - что? Неа. – Bergi

+0

Извинения, я должен что-то упустить. Когда вы «импортируете», он выполняет тело модуля после статического анализа и загрузки. Поэтому, если вы вызываете какие-либо функции в загружаемом файле (без определения каких-либо функций или классов), 'import' будет их выполнять, нет? –

+0

Я считаю, что модули выполняются один раз, а затем экспортированные значения возвращаются несколько раз (один раз для каждого оператора 'import'). – Max

1

Импорт загружается (и выполняется, если только циклический), прежде чем модуль будет выполнен статически. В вашем случае a.js будет загружен до того, как будет выполнен main.js.

Если у вас есть зависимости, вы должны объявить их в явном виде:

// random_prop.js 
window.randomProperty = function() { return "hi"; }; 
console.log("randomProperty set"); 

// a.js 
import "random_prop"; 
const a = { 
    prop: window.randomProperty; 
} 
console.log("Prop " + a.prop); 
export {a as default} 

// main.js 
import "babel-polyfill"; // Not sure if this is relevant 
import a from "a"; 
console.log(a.prop); 

Конечно, вы можете также import в random_prop.js в основном. js до a.js, и он будет работать в этой простой настройке, но я бы не рекомендовал полагаться на o n побочных эффектов.

+0

Является ли порядок выполнения импортированных модулей определенными в любом месте? Я пытаюсь установить 'document.domain', и для случайных модулей для создания глобальных изменений состояния действительно неверно. В этом конкретном случае лучше изменить глобальное состояние в одном месте, а именно в главном файле js. Я говорю это, потому что теоретически можно использовать этот модуль без необходимости изменять 'document.domain'. – Max

+0

Порядок выполнения модулей определяется ориентированным графом зависимостей и точкой входа. Кроме этого, загрузчики модулей могут делать все, что захотят. Действительно лучше сделать одно дело только в одном месте, для чего созданы модули. В моем решении это место является модулем 'random_prop.js', и все, кому нужно это изменение состояния, должны импортировать этот модуль. – Bergi

+0

Другим решением является отсрочка выполнения вещей в модуле 'a.js' путем его переноса в функцию и экспорта этого. Вы сможете использовать его несколько раз и в разных глобальных состояниях. Смотрите на это Бобби Матсонс. – Bergi

Смежные вопросы