Ticking Quine-Bomb!

JavaScript, 53 bytes

f=(d,t=1/0,n=Date.now()/1e3)=>n>t?'BOOM!':_=>f(d,d+n)

g=
f=(d,t=1/0,n=Date.now()/1e3)=>n>t?'BOOM!':_=>f(d,d+n)

// please notice that `delay` may take longer time than experted time on a slow / busy machine
// which may lead an incorrect result
delay=n=>new Promise(r=>setTimeout(r,n*1e3));

assertFine=s=>console.log(s!=='BOOM!'?s:'FAIL');
assertBoom=s=>console.log(s==='BOOM!'?s:'FAIL');

(async function () {
  console.log('start test');
  let p1 = g(3);
  assertFine(p1); // should not boom
  await delay(2);
  let p2 = p1();
  assertFine(p2); // should not boom
  await delay(2);
  let b1 = p1();
  assertBoom(b1); // should boom
  let p3 = p2();
  assertFine(p3); // should not boom
  await delay(2);
  let b2 = p2();
  assertBoom(b2); // should boom
}());


Old answer (returning should be a string)

JavaScript, 78 bytes

(f=(o,t,d)=>(x=d,n=Date.now()/1e3)=>o&&n>t?'BOOM!':`(f=${f})(${[1,n+x,x]})`)()

g=
(f=(o,t,d)=>(x=d,n=Date.now()/1e3)=>o&&n>t?'BOOM!':`(f=${f})(${[1,n+x,x]})`)()

// please notice that `delay` may take longer time than experted time on a slow / busy machine
// which may lead an incorrect result
delay=n=>new Promise(r=>setTimeout(r,n*1e3));

assertFine=s=>console.log(s!=='BOOM!'?s:'FAIL');
assertBoom=s=>console.log(s==='BOOM!'?s:'FAIL');

(async function () {
  console.log('start test');
  let p1 = g(3);
  assertFine(p1); // should not boom
  await delay(2);
  let p2 = eval(p1)();
  assertFine(p2); // should not boom
  await delay(2);
  let b1 = eval(p1)();
  assertBoom(b1); // should boom
  let p3 = eval(p2)();
  assertFine(p3); // should not boom
  await delay(2);
  let b2 = eval(p2)();
  assertBoom(b2); // should boom
}());


JavaScript, 51 bytes

f=(t,o=setTimeout(_=>o=0,t*1e3))=>_=>o?f(t):'BOOM!'

Test in browser

old version

f=(t,o=0)=>{setTimeout(()=>o=1,t*1000);return ()=>o?'BOOM!':f(t)}

Test in browser