
<script>
import {toggleLayer, showVariable, runExampleButton} from "src/client/essay.js"
""
</script>

## Idea: Scope async callbacsk (e.g. setTimeout) 

First we have to include ContextJS. 

```javascript {.includes .CountSetTimeoutLayer .PromiseExample .TimeoutExample}
import * as cop  from 'src/client/ContextJS/src/contextjs.js'

```

```javascript {.setTimeoutMethod .TimeoutExample .CountSetTimeoutLayer .NoResult}
// #ContextJS #bug cannot layer functions, setTimeout but only methods... but setTimeout is often called as function, and not as a method on an object
if (!window.setTimeoutMethod) {
  window.setTimeoutMethod = window.setTimeout
} 
window.setTimeout = function(callback, delay) {
  return window.setTimeoutMethod(callback, delay)
}

```

With with help of ContextJS layers, we can now simply count all timeout calls in the system. 

```javascript {.CountSetTimeoutLayer .TimeoutExample}
var timeoutCounter=0
cop.layer(self, "CountSetTimeoutLayer").refineObject(self, {
    setTimeoutMethod(callback, delay) {
      timeoutCounter++
      return cop.proceed(callback, delay)
    }
});

```

<div style="display:inline-block">
  <script>runExampleButton("CountSetTimeoutLayer", this)</script>
</div>
<div style="display:inline-block">
  <script>
    showVariable("timeoutCounter", this)
  </script>
</div>

But we don't know what they are, so we not only count them, but we can tally them.
We can use the name or just use the source, when the function is anonymous.  

```javascript {.TallyTimeoutLayer}
var tallyMap = new Map()
function tally(key) {
  tallyMap.set(key, (tallyMap.get(key) || 0 ) + 1) 
}

Array.from(tallyMap)
cop.layer(self, "TallyTimeoutLayer").refineObject(self, {
    setTimeoutMethod(callback, delay) {
      cop.withoutLayers([TallyTimeoutLayer], () => {
        tally("" + (callback.name || callback)) // callback object id changes.... but the string is the same
      })
      return cop.proceed(callback, delay)
    }
});

```

<script>runExampleButton("TallyTimeoutLayer", this)</script>
<script>
  showVariable("tallyMap", this)
</script>
