0

I was exploring import/export and stumbled upon this strange behaviour.

It looks like exporting promise function as variable declaration, automagically merges any imports together so it won't re-promise?

Imagine two cases: first:

/* *** fetchMe.js *** */
/ *********************/
var fetchMe = fetch('https://jsonplaceholder.typicode.com/todos/1')
  .then(response => response.json())
  .then(function (data) {
    console.log("fromFetch", data);
    return data.title
  });
 export default fetchMe

/* *** a.js *** */
/****************/
import fetchMe from "./fetchMe";

function a () {
  console.log("from a");
  fetchMe;
}

export default a

/* *** b.js *** */
/****************/
import fetchMe from "./fetchMe";

function b () {
  console.log("from b");
  fetchMe;
}

export default b

/* *** index.js *** */
/*******************/
import a from "./a";
import b from "./b";

a();
b();

// RESULTS //
// from a
// from b
// fromFetch <--- just once!

second case:

/* *** fetchMe.js *** */
 /*********************/
function fetchMe() {                // ** <-- DIFFERENCE
  fetch('https://jsonplaceholder.typicode.com/todos/1')
    .then(response => response.json())
    .then(function (data) {
      console.log("fromFetch", data);
      return data.title
    });
}

export default fetchMe

/* *** a.js *** */
/***************/
import fetchMe from "./fetchMe";

function a () {
  console.log("from a");
  fetchMe();                       // ** <-- DIFFERENCE
}

export default a

/* *** b.js *** */
/***************/
import fetchMe from "./fetchMe";

function b () {
  console.log("from b");
  fetchMe();                     // ** <-- DIFFERENCE
}

export default b

/* *** index.js *** */
/*******************/
import a from "./a";
import b from "./b";

a();
b();

// RESULTS //
// from a
// from b
// fromFetch <--- not once!
// fromFetch <--- twice!?

The only difference between them two is the fragment where the fetchMe is declared as function rather than a variable function.

Is it javascript way of importing a variable only once to save the amount of calls?

Why is calling twice on function call and only once when used as variable?

J. Doe
  • 301
  • 2
  • 13
  • 1
    The lines of code like `fetchMe;` do not do anything at all, regardless of the value of `fetchMe`. In the first case, `fetchMe` will be the Promise instance imported. – Pointy Jan 16 '19 at 15:52
  • 2
    I guess `fetchMe;` doesn't do anything, but importing the module runs the code inside it, which logs "from fetchMe". Importing it a second time doesn't re-run the module's code though. (in case it's not clear, you aren't declaring a variable function, you're assigning a Promise object to `var fetchMe`) –  Jan 16 '19 at 15:52
  • 1
    By "variable function" I guess you mean `var fetchMe = function () { ... };` If you use that in your module, the result will be the same as your second case. –  Jan 16 '19 at 15:57

1 Answers1

3

A module is only evaluated once, its exported variables essentially form a singleton. They are shared by all modules that import them.

In your first example, there is a single promise that is used (well, not really, referenced) twice.
In your second example, there is a single function that is called twice.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you for the answer. Additional question would be - is it possibly to call `fetchMe` once so the same result is shared between `a` and `b`, without having to fetch it twice? – J. Doe Jan 16 '19 at 16:27
  • Yes, by using [memoisation](https://en.wikipedia.org/wiki/Memoisation). You basically would declare a local variable in your module that is lazily initialised with the result (the promise) when the function is called for the first time, as soon as the promise exists the function would always return it again instead of doing another fetch. – Bergi Jan 16 '19 at 16:32