JSFiddle - React, Tailwind, and code Playground

by lid0

HTML

<div id="app">

  Ref Counter: {{ refCounter }}
  <div style="background:#cfcfcf;padding:10px;">
    <!--    <div>
      Waiting for async to return true : <b v-if="await(doSomethingAsyn, null)">WASSAAAA, true </b><b v-else>__________</b>
    </div> -->

    <div>


      <div class="app">
        Await same signature, different default values ( will use first for both )
        <!-- notice: the default will be ignored, due to memoization -->
        <!-- we use the default null, to "detect" pending state. (promise will resolev to boolean) -->
        <p>
          <b>async status/response: {{ await( ()=>doSomethingAsyn(1,2,3), "123")   }}</b>
        </p>
        <p>
          <b>async status/response: {{ await( ()=>doSomethingAsyn(1,2,3), "123 you are not going to see this")   }}</b>
        </p>
        <p>
          <!-- bypass memoization by changing content of arrow function commend to change signature -->
          <b>async status/response: {{ await( ()=>doSomethingAsyn(1,2,3/*uniqu_id*/), "123 bypassed cache")   }}</b>
        </p>
      </div>


      <div class="app">
        Await Bypass cache with different arguments


        <p>
          <b>async status/response: {{ await( ()=>doSomethingAsyn(1,2,4), "124, new ")   }}</b>
        </p>
      </div>



      <div class="app">
        awaitLazy (both will use the first default value):
        <p>
          <b>async status/response: {{ awaitLazy( doSomethingAsyn, "lazy call")   }}</b>
        </p>
        <p>
          <b>async status/response: {{ awaitLazy( doSomethingAsyn, "lazy call blabla")   }}</b>
        </p>
      </div>



    </div>



  </div>
    <pre style="font-size:11px">
  Vue - await for async in vue expression such as in v-if
  
  with arguments, we wrap in ()=>
   await( ()=>doSomethingAsyn(1,2,3), "123")  
  
  Lazy ( no arguments )
   awaitLazy( doSomethingAsyn, "lazy call") 
  
  
  </pre>

</div>

CSS

ul {
  float: left;
}

.app {
  margin-top: 3px;
  border: 1px solid gray;
  border-radius: 10px;
  background: #cfc;
  padding: 10px;
}

JavaScript

//author: lidlanca 2021 march 22

import { createApp, ref } from "https://unpkg.com/[email protected]/dist/vue.esm-browser.js";




const app = createApp({
  setup() {

    const awaitPromiseWeakMap = new WeakMap();
    const awaitPromiseMap = new Map()
    const refCounter = ref(0)

    function awaitPromiseLazy(func, defaultValue) {
      return awaitPromise(func, defaultValue, true);
    }

    /**
    
    when passing a func with argument wrap in fat arrow  ()=> someFunc(a,b,c)
    This will allow us to create a string based signature of the  function call, using function decomplilation 
    ()=> someFunc(a,b,c) 
    is different than
    ()=> someFunc(a,b,FF)
    
     func         - an async function, or a function that when called returns an Thenable/Promise
     defaultValue - the initial value used until the promise is resolved. 
     lazy         - when true, the func will be used as key in the WeakMap. 
    */
    function awaitPromise(func, defaultValue, lazy) {
      // 
      var funcSig;
      var map;
      if (lazy) {
        var funcSig = func
        map = awaitPromiseWeakMap
      } else {
        var funcSig = func.toString().replace(" ", "")
        map = awaitPromiseMap

      }


      console.log("TICK", funcSig)
      if (!awaitPromiseMap.has(funcSig)) {
        var r = ref(defaultValue);
        
        refCounter.value++;
        
        awaitPromiseMap.set(funcSig, r);
        func().then(function(v) { // update ref to resolved value
          r.value = v
        });
      } else {
        var r = awaitPromiseMap.get(funcSig)
      }
      return r.value
    }

    /**
    doSomethingAsync - will do something and resolve after 3 seconds.
    */
    async function doSomethingAsyn() {
      return new Promise(
        function(r) {
          setTimeout(function() {
            console.log("resolved")
            r(true)
          }, 3000)
        })
    }

    return {
      doSomethingAsyn,
      await: awaitPromise,
      awaitLazy:...