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