Skip to content

Instantly share code, notes, and snippets.

@WebReflection
Created December 30, 2020 11:03
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save WebReflection/e91dab813698100a4e0738858d582093 to your computer and use it in GitHub Desktop.
Save WebReflection/e91dab813698100a4e0738858d582093 to your computer and use it in GitHub Desktop.
const {isArray} = Array;
const sync = async values => {
for (let {length} = values, i = 0; i < length; i++) {
const value = await values[i];
values[i] = isArray(value) ? await sync(value) : value;
}
return values;
};
const asyncTag = tag => async (template, ...values) =>
tag(template, ...(await sync(values)));
// example
const asyncRaw = asyncTag(String.raw);
asyncRaw`a${Promise.resolve('b')}c`
.then(console.log); // "abc"
@WebReflection
Copy link
Author

WebReflection commented Dec 30, 2020

Bloat-free Transpilable Version

This is now a module

This version would not bloat once transpiled.

const {isArray} = Array;

const sync = (values, i) => {
  const resolved = [];
  for (const {length} = values; i < length; i++)
    resolved.push(isArray(values[i]) ? sync(values[i], 0) : values[i]);
  return Promise.all(resolved);
};

const asyncTag = tag => {
  function invoke(template, values) {
    return tag.apply(this, [template].concat(values));
  }
  return function (template) {
    return sync(arguments, 1).then(invoke.bind(this, template));
  };
};

@WebReflection
Copy link
Author

Sync mixed Async Behavior

This version does not necessarily return a Promise if all template values are not a Promise, but it might be confusing to use ... although, it's a proof of concept.

const {isArray} = Array;

const sync = (values, i) => {
  let isSync = true;
  const resolved = [];
  for (const {length} = values; i < length; i++) {
    let value = values[i];
    if (isArray(value))
      value = sync(value, 0);
    if (isSync && value instanceof Promise)
      isSync = false;
    resolved.push(value);
  }
  return isSync ? resolved : Promise.all(resolved);
};

const asyncTag = tag => {
  function invoke(template, values) {
    return tag.apply(this, [template].concat(values));
  }
  return function (template) {
    const values = sync(arguments, 1);
    return 'then' in values ?
            values.then(invoke.bind(this, template)) :
            invoke.call(this, template, values);
  };
};

// example
const asyncRaw = asyncTag(String.raw);

// async invoke
asyncRaw`a${[
  1,
  [2, [Promise.resolve(3)], 4],
  [5, 6]
]}${Promise.resolve(7)}c`
  .then(console.log); // "abc"

// direct invoke
console.log(asyncRaw`a${'b'}c`);

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