DEV Community

Masashi Hirano
Masashi Hirano

Posted on • Updated on

V8 6.3 shipped New ECMAScript features

V8 released 6.3 on October 25, 2017 (see: V8 JavaScript Engine)
It includes new features from ECMAScript proposal stage-3
It seems likely that they will also soon be implemented in Node.js

Now, you can try them with --hamony options or 3rd party libraries.
I developed demo on GitHub

Dynamic import

Specification

It is possible to load parts of a JavaScript application dynamically at runtime with this feature.
If you want to use a function from moduleA or moduleB, you may write code like below.

if (member.isLoggedIn()) {
  moduleA.func();
} else {
  moduleB.func();
}
Enter fullscreen mode Exit fullscreen mode

Using static import, you have to import both modules.

import moduleA from './moduleA';
import moduleB from './moduleB';

if (member.isLoggedIn()) {
  moduleA.func();
} else {
  moduleB.func();
}
Enter fullscreen mode Exit fullscreen mode

However, you can now dynamically import only the module you want to use with the dynamic import feature.

if (member.isLoggedIn()) {
  import('./moduleA.js') // load moduleA here
    .then(module => {
      module.func();
    });
} else {
  import('./moduleB.js') // load moduleB here
    .then(module => {
      module.func();
    });
}
Enter fullscreen mode Exit fullscreen mode

Also, you can use dynamic import with loop or promise.

for (let i = 0; i < MAX; i++) {
  import(`module${i}.js`)
    .then(module => {
      module.func();
    });
}
Enter fullscreen mode Exit fullscreen mode
promiseFunc()
  .then(res => {
    return import('./module.js');
  })
  .then(module => {
    module.func(data);
  });
Enter fullscreen mode Exit fullscreen mode

function import() returns Promise object and you can use async/await.

(async() => {
  if (member.isLoggedIn()) {
    const module = await import('./moduleA.js') // load moduleA
    module.func();
  } else {
    const module = await import('./moduleB.js') // load moduleB
    module.func();
  }
})()
Enter fullscreen mode Exit fullscreen mode

Demo
With Chrome 63 or later, check console or network panel and you can see the modules loaded dynamically at runtime.
Code is below.

(async() => {
    let count = 0;
    // load hello1、hello2、hello3 in a random order at runtime
    let id = setInterval(async() => {
      const i = Math.floor(Math.random() * 3) + 1;
      const module = await import(`./import_modules/hello${i}.js`);
      module.hello();
      count++;
      if (count === 10) {
          clearInterval(id);
      }
     }, 1000);
})();
Enter fullscreen mode Exit fullscreen mode

Using node-es-module-loader, it is available to run in Node.js.

Async Iteration

Specification

a.k.a Async Iterators / Generators
This supports asynchronously iterating data from async functions.
If you don't know iterator and generator, read this

Up to now, it's been possible to run async functions or APIs in parallel with Promise.all.

(async() => {
  const dataList = await Promise.all([
    fetch('https://qiita.com/api/v2/tags/Node.js'),
    fetch('https://qiita.com/api/v2/tags/JavaScript'),
    fetch('https://qiita.com/api/v2/tags/npm'),
  ]);
  for (const data of dataList) {
    console.log(data);
  }
})();
Enter fullscreen mode Exit fullscreen mode

However, calling many functions or APIs may make code too unwieldy.
Async Iterators make it easy to read.

(async() => {
  const promises = [];
  for (const tag of ["Node.js", "JavaScript", "npm"]) {
    promises.push(fetch(`https://qiita.com/api/v2/tags/${tag}`));
  }

  for await (const data of promises) {
    console.log(data)
  }
})();
Enter fullscreen mode Exit fullscreen mode

Async generators make it possible to customize iteration.
Demo
With Chrome 63 or later, check console or network panel and you can see api is called several times.
Code is below. Using axios.

/*
 * get random number
 */
async function* gen() {
  while (true) {
    const res = await axios.get('https://www.random.org/decimal-fractions/?num=1&dec=10&col=1&format=plain&rnd=new');
    const num = res.data;
    yield Number(num);
  }
}

(async() => {
  const BREAK = 0.8;
  for await (const num of gen()) {
    console.log(num);
    if (num > BREAK) {
      console.log("over", BREAK);
      break;
    }
  }
})();
Enter fullscreen mode Exit fullscreen mode

In Node.js, it is necessary to use --harmony_async_iteration option.

Promise.prototype.finally

Specification

As you know, this is like finally of try-catch-finally.
Up to now, if you wanted to execute some code regardless of whether an error will occur or not, you had to write said code in both the then() and catch() blocks of a Promise.

promiseFunc()
  .then(() => {
    someFunction();
    closeFunction(); // for successful
  })
  .catch(err => {
    console.log(err);
    closeFunction(); // for error
  });
Enter fullscreen mode Exit fullscreen mode

However, now, Promise.prototype.finally allows you to write code like the try-catch-finally pattern.

promiseFunc()
  .then(() => {
    someFunction();
  })
  .catch(err => {
    console.log(err);
  })
  .finally(() => {
    closeFunction();
  });
Enter fullscreen mode Exit fullscreen mode

Now, you can use try-catch-finally with async/await pattern.

(async() => {
  try {
    await promiseFunc();
    await someFunction();
  } catch (err) {
    console.log(err);
  } finally {
    closeFunction();
  }
})();
Enter fullscreen mode Exit fullscreen mode

Demo
Code is below.

Promise.resolve("resolve")
  .then(val => {console.log(val);return "then"})
  .then(val => {console.log(val);throw new Error("catch")})
  .catch(err => {console.log(err.message)})
  .finally(() => {console.log("finally")});
Enter fullscreen mode Exit fullscreen mode

With Chrome 63 or later, check console panel and you can see resolve(), then(), catch() and finally() are called.

In Node.js, it is necessary to use --harmony_promise_finally option.

Further reading

Thanks

@shimataro999 and @mackles93 reviewed this post.

Thanks.

Discussion (0)