Skip to content

Instantly share code, notes, and snippets.

@shisama
Last active December 4, 2017 07:43
Show Gist options
  • Save shisama/7508e456596cb78aa974de25545f7fe5 to your computer and use it in GitHub Desktop.
Save shisama/7508e456596cb78aa974de25545f7fe5 to your computer and use it in GitHub Desktop.

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();
}

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();
}

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();
    });
}

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();
    });
}
promiseFunc()
  .then(res => {
    return import('./module.js');
  })
  .then(module => {
    module.func(data);
  });

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();
  }
})()

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);
})();

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);
  }
})();

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)
  }
})();

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;
    }
  }
})();

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
  });

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();
  });

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

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

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")});

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment