Salut les gars, j'ai du mal à comprendre comment asynchroniser et attendre fonctionne en coulisses. Je sais que nous avons des promesses qui rendent notre code non bloquant en utilisant la fonction "alors", nous pouvons placer tout le travail que nous devons faire une fois la promesse résolue. et le travail que nous voulons faire en parallèle pour promettre de l'écrire en dehors de notre fonction d'alors. Le code devient donc non bloquant. Cependant, je ne comprends pas comment le async
await
fait du code non bloquant.
async function myAsyncFunction() {
try {
let data = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// It will not run this line until it resolves await.
let result = 2 + 2;
return data;
}catch (ex){
return ex;
}
}
Voir le code ci-dessus. Je ne peux pas avancer tant que l'appel API n'est pas résolu. Si cela rend mon code bloquant le code, comment est-il meilleur que promis? Ou y a-t-il quelque chose que j'ai manqué à propos de async
et await
? Où dois-je mettre mon code qui ne dépend pas de l'appel en attente? afin qu'il puisse continuer à fonctionner sans attendre la tenue de l'exécution?
J'ajoute un code Promise que je voudrais répliquer dans un exemple d'attente asynchrone.
function myPromiseAPI() {
myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
// data
});
// runs parallel
let result = 2 + 2;
}
Tout comme son nom l'indique, le mot clé await
fera "attendre" jusqu'à ce que sa promesse soit résolue avant d'exécuter la ligne suivante. L'intérêt de await
est de faire attendre le code jusqu'à la fin de l'opération avant de continuer.
La différence entre ce code et le code de blocage est que le monde extérieur la fonction peut continuer à s'exécuter pendant que la fonction attend la fin des opérations asynchrones.
async
et await
ne sont que du sucre syntaxique en plus des promesses. Ils vous permettent d'écrire du code qui ressemble beaucoup au code synchrone ordinaire même s'il utilise des promesses sous les couvertures. Si nous traduisions votre exemple là-bas en quelque chose qui fonctionnait explicitement avec les promesses, cela ressemblerait à quelque chose comme:
function myAsyncFunction() {
return myAPICall('https://jsonplaceholder.typicode.com/posts/1')
.then(function (data) {
let result = 2 + 2;
return data;
})
.catch(function (ex) {
return ex;
});
}
Comme nous pouvons le voir ici, la ligne let result = 2 + 2;
Est à l'intérieur d'un gestionnaire .then()
, ce qui signifie qu'elle ne s'exécutera pas tant que myAPICall()
ne sera pas résolu. C'est la même chose lorsque vous utilisez await
. await
résume simplement la .then()
pour vous.
Une chose à garder à l'esprit (et je pense que le point que vous recherchez) est que vous n'avez pas à utiliser await
tout de suite. Si vous avez écrit votre fonction comme ceci, vous pouvez exécuter votre ligne let result = 2 + 2;
Immédiatement:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// just starting the API call and storing the promise for now. not waiting yet
let dataP = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let result = 2 + 2;
// Executes right away
console.log('result', result);
// wait now
let data = await dataP;
// Executes after one second
console.log('data', data);
return data;
} catch (ex) {
return ex;
}
}
myAsyncFunction();
Après quelques éclaircissements, je peux voir que ce que vous vouliez vraiment savoir, c'est comment éviter d'avoir à attendre deux opérations asynchrones une par une et à la place de les exécuter en parallèle. En effet, si vous utilisez un await
après l'autre, le second ne démarrera pas avant la fin du premier:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
let data1 = await myAPICall('https://jsonplaceholder.typicode.com/posts/1');
// logs after one second
console.log('data1', data1);
let data2 = await myAPICall('https://jsonplaceholder.typicode.com/posts/2');
// logs after one more second
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
Pour éviter cela, ce que vous pouvez faire est démarrer les deux opérations asynchrones en les exécutant sans les attendre, en affectant leurs promesses à certaines variables. Ensuite, vous pouvez attendre les deux promesses:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both lines execute right away
let dataP1 = myAPICall('https://jsonplaceholder.typicode.com/posts/1');
let dataP2 = myAPICall('https://jsonplaceholder.typicode.com/posts/2');
let data1 = await dataP1;
let data2 = await dataP2;
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();
Une autre façon de procéder consiste à utiliser Promise.all()
avec une décomposition de tableau:
const timeout =
seconds => new Promise(res => setTimeout(res, seconds * 1000));
function myAPICall() {
// simulate 1 second wait time
return timeout(1).then(() => 'success');
}
async function myAsyncFunction() {
try {
console.log('starting');
// both myAPICall invocations execute right away
const [data1, data2] = await Promise.all([
myAPICall('https://jsonplaceholder.typicode.com/posts/1'),
myAPICall('https://jsonplaceholder.typicode.com/posts/2'),
]);
// logs after one second
console.log('data1', data1);
console.log('data2', data2);
} catch (ex) {
return ex;
}
}
myAsyncFunction();