Maison  >  Article  >  interface Web  >  Une plongée approfondie dans les fonctions asynchrones en JavaScript

Une plongée approfondie dans les fonctions asynchrones en JavaScript

青灯夜游
青灯夜游avant
2022-11-03 20:36:441553parcourir

Une plongée approfondie dans les fonctions asynchrones en JavaScript

Fonction async

La valeur de retour de la fonction asynchrone est l'objet de promesse, et le résultat de l'objet de promesse est déterminé par la valeur de retour de l'exécution de la fonction asynchrone. La fonction async peut rendre les opérations asynchrones plus pratiques. En bref, c'est le sucre syntaxique de Generator.

Définissez une fonction asynchrone.La caractéristique est que même si le résultat de retour interne de la fonction n'est pas un objet de promesse, le résultat de retour final de l'appel de la fonction est toujours un objet de promesse. suit : Si le résultat renvoyé n'est pas un objet Promise Dans ce cas :

<script>
    async function fn(){
        // 返回的结果是字符串
        // return &#39;123&#39;
        // // 返回的结果是undefined
        // return;
        // 返回的结果是抛出一个异常
        throw new &#39;error&#39;
    }
    const result = fn()
    console.log(result);
</script>

Si le résultat renvoyé est un objet Promise, nous pouvons utiliser la méthode then normalement, comme suit :

<script>
    async function fn(){
        return new Promise((resolve,reject)=>{
            // resolve(&#39;成功的数据&#39;)
            reject(&#39;失败的数据&#39;)
        })
    }
    const result = fn()
    // 调用 then 方法
    result.then((value)=>{
        console.log(value);
    },(reason)=>{
        console.log(reason); // 打印失败的数据
    })
</script>

await expression

Grâce à l'introduction ci-dessus d'async, j'ai l'impression que sa fonction est un peu insipide, en fait ce n'est pas le cas, mais async doit être utilisé avec wait pour obtenir l'effet de sucre syntaxique.

await caractéristiques : await doit être écrit dans la fonction asynchrone

await L'expression du côté droit est généralement un objet de promesse

await renvoie la valeur du succès de la promesse

la promesse d'attente a échoué, An une exception sera levée, qui doit être capturée et traitée via try...catch

Pour parler franchement : wait est équivalent à la première fonction de rappel de la méthode then, ne renvoyant que les valeurs réussies, et try pour les valeurs échouées ..catch à capturer. Une erreur générée dans la fonction asynchrone entraînera le rejet de l'objet Promise renvoyé. L'objet d'erreur généré sera reçu par la fonction de rappel de la méthode catch.

<script>
    const p = new Promise((resolve,reject)=>{
        // resolve(&#39;用户数据&#39;)
        reject(&#39;用户加载数据失败了&#39;)
    })
    async function fn(){
        // 为防止promise是失败的状态,加上try...catch进行异常捕获
        try {
            // await 返回的结果就是 promise 返回成功的值
            let result = await p
            console.log(result);
        } catch (error) {
            console.log(error);//因为是失败的状态,所以打印:用户加载数据失败了
        }
    }
    fn()
</script>

Résumé :

(1)L'objet Promise derrière la commande wait peut être rejeté en conséquence, il est donc préférable de mettre la commande wait dans le code try...catch bloc.

(2)S'il y a des opérations asynchrones derrière plusieurs commandes d'attente, s'il n'y a pas de relation ultérieure, il est préférable de les laisser se déclencher en même temps. Par exemple : wait Promise.all([a(), b()]), voici une brève mention

(3)la commande wait ne peut être utilisée que dans des fonctions asynchrones, si elle est utilisée dans des fonctions ordinaires , Une erreur sera signalée.

(4)(Comprendre le principe de fonctionnement de l'async) La fonction asynchrone peut conserver la pile en cours d'exécution lorsqu'une tâche asynchrone est exécutée dans une fonction normale, si la tâche asynchrone se termine, la fonction normale peut avoir a terminé son exécution depuis longtemps et l'environnement de contexte de la tâche asynchrone a disparu. Si une tâche asynchrone signale une erreur, la pile d'erreurs n'inclura pas les fonctions ordinaires pendant l'exécution de la tâche asynchrone à l'intérieur de la fonction asynchrone, la fonction asynchrone suspend l'exécution, donc une fois que la tâche asynchrone à l'intérieur de la fonction asynchrone s'exécute et qu'une erreur est signalée, la pile d'erreurs inclura les fonctions asynchrones.

Formulaire d'utilisation async

// 函数声明
async function foo() {}
 
// 函数表达式
const foo = async function () {};
 
// 对象的方法
let obj = { async foo() {} };
obj.foo().then(...)
 
// Class 的方法
class Storage {
  constructor() {
    this.cachePromise = caches.open(&#39;avatars&#39;);
  }
 
  async getAvatar(name) {
    const cache = await this.cachePromise;
    return cache.match(`/avatars/${name}.jpg`);
  }
}
 
const storage = new Storage();
storage.getAvatar(&#39;jake&#39;).then(…);
 
// 箭头函数
const foo = async () => {};

async lit les fichiers

Identique à la promesse de lire le contenu du fichier expliquée précédemment, nous pouvons également utiliser async pour lire le fichier, le code est le suivant :

// 1.引入 fs 模块
const fs = require(&#39;fs&#39;)
 
// 2.读取文件
function index(){
    return new Promise((resolve,reject)=>{
        fs.readFile(&#39;./index.md&#39;,(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}
function index1(){
    return new Promise((resolve,reject)=>{
        fs.readFile(&#39;./index1.md&#39;,(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}
function index2(){
    return new Promise((resolve,reject)=>{
        fs.readFile(&#39;./index2.md&#39;,(err,data)=>{
            // 如果失败
            if(err) reject(err)
            // 如果成功
            resolve(data)
        })
    })
}
 
// 3.声明一个 async 函数
async function fn(){
    let i = await index()
    let i1 = await index1()
    let i2 = await index2()
    console.log(i.toString());
    console.log(i1.toString());
    console.log(i2.toString());
}
fn()

async envoie des requêtes AJAX

Semblable à l'explication précédente de

promesse d'envoi de requêtes ajax

, nous pouvons également utiliser async pour envoyer des requêtes ajax. Le code est le suivant :

<script>
    // 发送 AJAX请求,返回的结果是 Promise 对象
    function sendAjax(url){
        return new Promise((resolve,reject)=>{
            // 创建对象
            const x = new XMLHttpRequest()
 
            // 初始化
            x.open(&#39;GET&#39;,url)
 
            // 发送
            x.send()
 
            // 事件绑定
            x.onreadystatechange = function(){
                if(x.readyState === 4){
                    if(x.status >= 200 && x.status < 300){
                        // 如果响应成功
                        resolve(x.response)
                        // 如果响应失败
                        reject(x.status)
                    }
                }
            }
        })
    }
        
    // promise then 方法测试
    // const result = sendAjax("https://ai.baidu.com/").then(value=>{
    //     console.log(value);
    // },reason=>{})
    // async 与 await 测试
    async function fn(){
        // 发送 AJAX 请求
        let result = await sendAjax("https://ai.baidu.com/")
        console.log(result);
    }
    fn()
</script>

Par rapport à Generator

. Nous avons constaté que la relation entre async et wait est très similaire à la relation entre Generator et rendement. Les amis qui ne connaissent pas Generator peuvent lire mon article précédent :

Generator Explanation

après une comparaison, nous avons trouvé que : la fonction async ; est la fonction Générateur Remplacez l'astérisque (*) par async et remplacez rendement par wait. La comparaison de code est la suivante :

<script>
    // Generator 函数
    function * person() {
        console.log(&#39;hello world&#39;);
        yield &#39;第一分隔线&#39; 
    
        console.log(&#39;hello world 1&#39;);
        yield &#39;第二分隔线&#39;
    
        console.log(&#39;hello world 2&#39;);
        yield &#39;第三分隔线&#39;
    }
    let iterator = person()
    // console.log(iterator); 打印的就是一个迭代器对象,里面有一个 next() 方法,我们借助next方法让它运行
    iterator.next()
    iterator.next()
    iterator.next()
 
    // async函数
    const person1 = async function (){
        console.log(&#39;hello world&#39;);
        await &#39;第一分隔线&#39; 
    
        console.log(&#39;hello world 1&#39;);
        await &#39;第二分隔线&#39;
    
        console.log(&#39;hello world 2&#39;);
        await &#39;第三分隔线&#39;
    }
    person1()
</script>

Le principe d'implémentation de la fonction asynchrone est d'envelopper la fonction Générateur et l'exécuteur automatique dans une fonction.

<script>
    async function fn(args) {}
    // 等同于
    function fn(args) {
        // spawn函数就是自动执行器
        return spawn(function* () {});
    }
</script>

Nous pouvons analyser les caractéristiques et le style d'écriture du générateur et du code asynchrone :

<script>
    // Generator 函数
    function Generator(a, b) {
        return spawn(function*() {
            let r = null;
            try {
                for(let k of b) {
                r = yield k(a);
                }
            } catch(e) {
                /* 忽略错误,继续执行 */
            }
            return r;
        });
    }
 
    // async 函数
    async function async(a, b) {
        let r = null;
        try {
            for(let k of b) {
            r = await k(a);
            }
        } catch(e) {
         /* 忽略错误,继续执行 */
        }
        return r;
    }
</script>

所以 async 函数的实现符合语义也很简洁,不用写Generator的自动执行器,改在语言底层提供,因此代码量少。 

从上文代码我们可以总结以下几点

(1)Generator函数执行需要借助执行器,而async函数自带执行器,即async不需要像生成器一样需要借助 next 方法才能执行,而是会自动执行。

(2)相比于生成器函数,我们可以看到 async 函数的语义更加清晰

(3)上面就说了,async函数可以接受Promise或者其他原始类型,而生成器函数yield命令后面只能是Promise对象或者Thunk函数。

(4)async函数返回值只能是Promise对象,而生成器函数返回值是 Iterator 对象

【推荐学习:javascript高级教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer