Node.js Eventloop неожиданное поведение

241
05 марта 2021, 19:00
const https = require('https');
const crypto = require('crypto');
const fs = require('fs');
const start = Date.now();
function doRequest() {
    https.request('https://google.com', res => {
        res.on('data', () => { })
        res.on('end', () => {
            console.log('RQ:', Date.now() - start)
        })
    }).end()
}
function doHash(a) {
    crypto.pbkdf2('a', 'b', 100000, 512, 'sha512', () => {
        console.log('Hash:', a, ' ', Date.now() - start)
    })
}
doRequest()
fs.readFile('async.js', 'utf8', () => {
    console.log('FS:', Date.now() - start)
})
fs.readFile('async.js', 'utf8', () => {
    console.log('FS:', Date.now() - start)
})
fs.readFile('async.js', 'utf8', () => {
    console.log('FS:', Date.now() - start)
})
fs.readFile('async.js', 'utf8', () => {
    console.log('FS:', Date.now() - start)
})

doHash(1)
doHash(2)
doHash(3)
doHash(4)

Если запустить код в консоли то вывод следующий

RQ: 145
Hash: 1   1184
FS: 1185
FS: 1186
FS: 1186
FS: 1186
Hash: 3   1194
Hash: 2   1194
Hash: 4   1207

Node по умолчанию использует 4 потока, в них попадает 4 задачи на чтение файла, когда один из потоков освобождается так как требуется ждать ответа от жесткого диска он выполняет следующую задачу это как раз одна из функций doHash() она иполняется, затем приходят ответы от жесткого исполняются все fs.readFile, а затем оставшиеся в очереди doHash()

но если в конце кода убрать doHash(4) то вывод следующий

FS: 64
FS: 70
FS: 70
FS: 70
RQ: 164
Hash: 1   925
Hash: 2   934
Hash: 3   956

то есть в данном случае почему-то при простаивание не берется из очереди функция doHash() а исполняются сперва все fsReadFile()?

Answer 1

Вообще, причина подобного поведения в том, что вы пишите асинхронный код, нода просто запускает их в фоне и не ждет окончания выполнения функции, запуская код далее.

Если вы хотите, чтобы все выполнялось синхронно - измените код на следующий

function doRequest() {
    return new Promise((resolve, reject)=>{
        https.request('https://google.com', res => {
            res.on('data', () => { })
            res.on('end', () => {
                console.log('RQ:', Date.now() - start)
                resolve()
            })
            res.on('error', (e)=>{
                reject(e)
            })
        }).end()
    })
}
function doHash(a) {
    crypto.pbkdf2Sync('a', 'b', 100000, 512, 'sha512', () => {
        console.log('Hash:', a, ' ', Date.now() - start)
    })
}
doRequest().then(()=>{
    fs.readFileSync('async.js', 'utf8', () => {
        console.log('FS:', Date.now() - start)
    })
    fs.readFileSync('async.js', 'utf8', () => {
        console.log('FS:', Date.now() - start)
    })
    fs.readFileSync('async.js', 'utf8', () => {
        console.log('FS:', Date.now() - start)
    })
    fs.readFileSync('async.js', 'utf8', () => {
        console.log('FS:', Date.now() - start)
    })
    doHash(1)
    doHash(2)
    doHash(3)
    doHash(4)
}).catch(err=>{
    throw err;
})
READ ALSO
Как скрыть некоторые option у тега select на чистом JS

Как скрыть некоторые option у тега select на чистом JS

У меня есть тег select с тегами option

270
Не могу подключиться к postgresql в react приложении с помощью пакета 'pg' (node-postgres)

Не могу подключиться к postgresql в react приложении с помощью пакета 'pg' (node-postgres)

Задача: подключить БД Postgresql 11 к проекту на React для получения оттуда данныхНе могу найти документацию, соответствующую реальности или примеры...

106
Пакеты NPM и VK

Пакеты NPM и VK

Как установить пакет ни по инструкциям в документации VK, ни по инструкциям документации NPM и ни по инструкциям интернета так и не удалосьА...

301
Maximum call stack size exceeded

Maximum call stack size exceeded

При выполнении кода вылетает данная ошибка, не понимаю почему

93