javascript single-threaded , how asynchronous is implemented

It is acknowledged that JavaScript is single-threaded ,but while i try the code below, when i use setTimeout and Promise, it’s obviously that they runs asynchronously

function testTimer(){
  setTimeout(()=>{console.log(2)},100)
}
function testLoop(){
    for(let i = 0; i < 1e3; i++){}
    console.log(3)
}
function testPromise(){
     return new Promise((resolve)=>{
        for(let i = 0; i < 1e3; i++){}
        resolve();
    })
}
console.log(1)
testTimer();
testLoop();
console.log(4)
testPromise().then(()=>{console.log(5)})
console.log(6)

If javascript is completely single-threaded, the console should print 1, 2, 3, 4, 5, 6 in order. But the single threaded feature can only be seen in testLoop(), we can see that the use of Promise and setTimeout allow the code below run ahead, could someone please tell how’s this achieved?