Kombinacja funkcji async + wait + setTimeout
Próbuję korzystać z nowych funkcji asynchronicznych i mam nadzieję, że rozwiązanie mojego problemu pomoże innym w przyszłości. To jest mój kod, który działa:
async function asyncGenerator() {
// other code
while (goOn) {
// other code
var fileList = await listFiles(nextPageToken);
var parents = await requestParents(fileList);
// other code
}
// other code
}
function listFiles(token) {
return gapi.client.drive.files.list({
'maxResults': sizeResults,
'pageToken': token,
'q': query
});
}
Problem polega na tym, że moja pętla while działa zbyt szybko i skrypt wysyła zbyt wiele żądań na sekundę do google API. Dlatego chciałbym zbudować funkcję snu, która opóźnia żądanie. Mógłbym więc użyć tej funkcji również do opóźniania innych żądań. Jeśli istnieje inny sposób na opóźnienie żądania, proszę pozwolić mi wiedzieć.
W każdym razie, to jest mój nowy kod, który nie działa. Odpowiedź żądania jest zwracana do anonimowej funkcji asynchronicznej w setTimeout, ale po prostu nie wiem, w jaki sposób mogę zwrócić odpowiedź na funkcję sleep resp. do początkowej funkcji asynchronicznego generatora.
async function asyncGenerator() {
// other code
while (goOn) {
// other code
var fileList = await sleep(listFiles, nextPageToken);
var parents = await requestParents(fileList);
// other code
}
// other code
}
function listFiles(token) {
return gapi.client.drive.files.list({
'maxResults': sizeResults,
'pageToken': token,
'q': query
});
}
async function sleep(fn, par) {
return await setTimeout(async function() {
await fn(par);
}, 3000, fn, par);
}
Wypróbowałem już kilka opcji: zapisanie odpowiedzi w zmiennej globalnej i zwrócenie jej z funkcji sleep, wywołanie zwrotne w funkcji anonimowej itp.
4 answers
Twoja sleep
funkcja nie działa, ponieważ setTimeout
nie działa (jeszcze?) zwróć obietnicę, która może być await
ed. Musisz to obiecać ręcznie:
function timeout(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function sleep(fn, ...args) {
await timeout(3000);
return fn(...args);
}
Btw, aby spowolnić pętlę, prawdopodobnie nie chcesz używać funkcji sleep
, która przyjmuje callback i odkłada go w ten sposób. Raczej polecam zrobić coś takiego
while (goOn) {
// other code
var [parents] = await Promise.all([
listFiles(nextPageToken).then(requestParents),
timeout(5000)
]);
// other code
}
Co pozwala obliczyć parents
zająć co najmniej 5 sekund.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-23 00:26:46
od węzła 7.6 można łączyć funkcje promisify
z modułu utils z setTimeout()
.
Węzeł.js
const sleep = require('util').promisify(setTimeout)
Javascript
const sleep = m => new Promise(r => setTimeout(r, m));
Użycie
async function main() {
console.time("Slept for")
await sleep(3000)
console.timeEnd("Slept for")
}
main()
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-21 19:57:11
setTimeout
nie jest funkcją async
, więc nie można jej używać z ES7 async-wait. Ale możesz zaimplementować swoją sleep
funkcję używając ES6 Promise :
function sleep (fn, par) {
return new Promise((resolve) => {
// wait 3s before calling fn(par)
setTimeout(() => resolve(fn(par)), 3000)
})
}
Wtedy będziesz mógł użyć tej nowej funkcji sleep
z ES7 async-wait:
var fileList = await sleep(listFiles, nextPageToken)
Proszę zauważyć , że odpowiadam tylko na pytanie dotyczące połączenia ES7 async / wait z setTimeout
, chociaż może to nie pomóc rozwiązać problemu z wysyłaniem zbyt wielu żądań na sekundę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-13 21:57:09
Szybka jednowierszowa, inline way
await new Promise((resolve) => setTimeout(() => resolve(), 1000));
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-27 21:22:30