Maison > interface Web > js tutoriel > Comprendre la promesse, asynchrone, attendre

Comprendre la promesse, asynchrone, attendre

hzc
Libérer: 2020-07-04 09:50:13
avant
1920 Les gens l'ont consulté

L'article précédent parlait principalement de synchronisation et d'asynchronisme, de la « pile d'exécution », de la « file d'attente de messages », ainsi que des « macro-tâches » et des « micro-tâches » dérivées de chacune d'elles. Si vous comprenez ces concepts. Je n'en sais pas grand chose, vous pouvez aller sur ce lien :

https://www.jianshu.com/p/61e7844e68d8

Les macro-tâches et les micro-tâches sont asynchrones, y compris ajax requêtes et timing du serveur, etc. Ayons une compréhension préliminaire de la promesse et sachons que c'est un moyen de résoudre les problèmes asynchrones. Alors, quelles sont les méthodes que nous utilisons couramment ?

Parce que cela implique beaucoup de points de connaissances, cet article parle principalement des fonctions de rappel et des promesses :

1. La fonction de rappel

先上代码:
function f2() {
    console.log('2222')
}
function f1(callback){
    console.log('111')
  setTimeout(function () {
    callback(); 
  }, 5000);
  console.log('3333')
}
f1(f2);

先看下打印值是:
111
3333
五秒后2222
Copier après la connexion

est équivalente au thread principal qui termine son exécution, et la fonction f2 sera appelée via la fonction de rappel. Cela n'a rien de mal à cela. Mais regardez l'exemple suivant :

现在我们读取一个文件,fileReader就是一个异步请求

// 这个异步请求就是通过回调函数的方式获取的

var reader = new FileReader()
var file = input.files[0]
reader.readAsText(file, 'utf-8',function(err, data){
    if(err){
        console.log(err)
    } else {
        console.log(data)
    }
})
Copier après la connexion

Cela a l'air très bien maintenant, mais s'il y a une erreur dans le téléchargement du fichier, nous devons porter un jugement dans le rappel. Si nous finissons de lire ce fichier, nous devons le faire. lire plusieurs Où sont les fichiers ? Doit-il être écrit comme ceci :

读取完文件1之后再接着读取文件2、3

var reader = new FileReader()
var file = input.files[0]
reader.readAsText(file1, 'utf-8',function(err1, data1){
    if(err1){
        console.log(err1)
    } else {
        console.log(data1)
    }
    reader.readAsText(file2, 'utf-8',function(err2, data2){
        if(err2){
            console.log(err2)
        } else {
            console.log(data2)
        }
        reader.readAsText(file3, 'utf-8',function(err3, data3){
            if(err3){
                console.log(err3)
            } else {
                console.log(data3)
            }
        })
    })
})
Copier après la connexion

L'écrire de cette façon peut répondre aux exigences, mais la lisibilité de ce code est relativement mauvaise et il n'a pas l'air si élégant, ce que nous appelons souvent « l'enfer des rappels ». . Alors, comment pirater ce rappel imbriqué ? ES6 nous fournit des promesses :

2. promesse

Tout d’abord, comprenons ce qu’est littéralement une promesse ? La promesse peut se traduire par un engagement et une garantie. Vous pouvez comprendre cet endroit comme :

Ma copine m'a demandé de faire quelque chose, même si je ne l'ai pas encore terminé, je vous promets qu'il y aura un résultat pour vous. Succès (réalisé) ou échec (rejeté) et état d'attente (en attente).

还是先上例子

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2000) // 成功以后这个resolve会把成功的结果捕捉到
        // reject(2000) // 失败以后这个reject会把失败的结果捕捉到
    }, 1000)
    console.log(1111)
})

promise.then(res => {
    console.log(res) // then里面第一个参数就能拿到捕捉到的成功结果
}, err =>{
    console.log(res)// then里面第二个参数就能拿到捕捉到的失败结果
})

打印结果:

1111
2000(一秒以后)
Copier après la connexion

1. Opération en chaîne Then

La méthode then de l'objet Promise renvoie un nouvel objet Promise, donc la méthode then peut être appelée via la chaîne. La méthode

then reçoit deux fonctions comme paramètres.Le premier paramètre est le rappel lorsque Promise est exécuté avec succès, et le deuxième paramètre est le rappel lorsque Promise ne parvient pas à s'exécuter. L'exemple ci-dessus le montre très clairement. les paramètres capturent le rappel échoué.

Une seule des deux fonctions sera appelée. Comment comprenez-vous cette phrase ?
Votre copine vous demande de préparer une soupe aux tomates et aux œufs. Soit vous le faites, soit vous ne le faites pas et commandez des plats à emporter. Il n'y a certainement pas de troisième option.

La valeur de retour de la fonction sera utilisée pour créer l'objet Promise renvoyé d'ici là. Comment faut-il comprendre cette phrase ? Toujours l'exemple ci-dessus :

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2000)
    }, 1000)
    console.log(1111)
})
promise.then(res => {
    console.log(res) // 这个地方会打印捕捉到的2000
    return res + 1000 // 这个函数的返回值,返回的就是这个promise对象捕捉到的成功的值
}).then(res => {
    console.log(res) //这个地方打印的就是上一个promise对象return的值
})

所以打印顺序应该是:

1111
2000
3000
Copier après la connexion

Nous venons de voir qu'il accepte alors deux paramètres, l'un est un rappel de réussite et l'autre est un rappel d'échec. Cela ne semble pas si élégant. En plus de cela, promis également. fournit une méthode catch. :

2. Opération de capture Catch

Cette capture est spécifiquement conçue pour capturer les rappels d'erreur :

let promise = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(2000) // 失败以后这个reject会把失败的结果捕捉到
    }, 1000)
    console.log(1111)
})
promise.catch(res => {
    console.log(res) // catch里面就能拿到捕捉到的失败结果
})

打印结果:

1111
2000(一秒以后)
Copier après la connexion

En plus de. then et catch, promise has aussi Nous utilisons également les deux syntaxes, all et race, brièvement :

3, all

Maintenant, nous avons une telle exigence Il y a trois interfaces A, B,. et C. Trois sont nécessaires une fois que toutes les interfaces ont réussi, la quatrième requête peut être lancée. Comment la mettre en œuvre ?

Appels enchaînés

let getInfoA = new Promise((resolve, reject) => {
    console.log('小A开始执行了')
    resolve()
}).then(res => {
    let getInfoB = new Promise((resolve, reject) => {
        console.log('小B开始执行了')
        resolve()
    }).then(res => {
        let getInfoC = new Promise((resolve, reject) => {
            console.log('小C开始执行了')
            resolve()
        }).then(res => {
            console.log('全都执行完了!')
        })
    })
})
Copier après la connexion

C'est une couche dans une autre, ça n'a pas l'air si élégant

tout

let getInfoA = new Promise((resolve, reject) => {
    console.log('小A开始执行了')
    resolve()
})
let getInfoB = new Promise((resolve, reject) => {
    console.log('小B开始执行了')
    resolve()
})
let getInfoC = new Promise((resolve, reject) => {
    console.log('小C开始执行了')
    resolve()
})
Promise.all([getInfoA, getInfoB, getInfoC]).then(res => {
   console.log('全都执行完了!')
})
Copier après la connexion

Reçoit un tableau d'objets Promise en tant que paramètre , lorsque l'état de tous les objets Promise de ce tableau est résolu ou rejeté, il appellera la méthode then. Si parfait, si élégant.

4. course

Maintenant, il y a une autre exigence, qui est également l'interface A, B, C. Tant que l'une d'elles répond, je peux ajuster l'interface D. Alors comment l'implémenter ?

1. Méthode traditionnelle

let getInfoA = new Promise((resolve, reject) => {
    console.log('小A开始执行了')
    setTimeout((err => {
        resolve('小A最快')
    }),1000)
}).then(res =>{
    console.log(res)
})
let getInfoB = new Promise((resolve, reject) => {
    console.log('小B开始执行了')
    setTimeout((err => {
        resolve('小B最快')
    }),1001)
}).then(res =>{
    console.log(res)
})
let getInfoC = new Promise((resolve, reject) => {
    console.log('小C开始执行了')
    setTimeout((err => {
        resolve('小C最快')
    }),1002)
}).then(res =>{
    console.log(res)
})

打印结果

小A开始执行了
小B开始执行了
小C开始执行了
小A最快
Copier après la connexion

Cette méthode doit être écrite trois fois, et elle ne semble pas si élégante. Voyons comment écrire race ?

2. race

let getInfoA = new Promise((resolve, reject) => {
    console.log('小A开始执行了')
    setTimeout((err => {
        resolve('小A最快')
    }),1000)
})
let getInfoB = new Promise((resolve, reject) => {
    console.log('小B开始执行了')
    setTimeout((err => {
        resolve('小B最快')
    }),1001)
})
let getInfoC = new Promise((resolve, reject) => {
    console.log('小C开始执行了')
    setTimeout((err => {
        resolve('小C最快')
    }),1002)
})
Promise.race([getInfoA, getInfoB, getInfoC]).then(res => {
    console.log(res)
})

打印结果

小A开始执行了
小B开始执行了
小C开始执行了
小A最快
Copier après la connexion

Semblable à Promise.all, Promise.race prend un tableau composé d'objets Promise comme paramètres. La différence est que l'un des objets Promise du tableau. Lorsque le statut Promsie passe à résolu ou rejeté, la méthode .then peut être appelée.

Promise est une méthode utilisée par ES6 pour résoudre les problèmes asynchrones. Elle est désormais largement utilisée. Par exemple, axios, que nous utilisons souvent, est encapsulé par promise et est très pratique à utiliser.

En plus des promesses, ES6 nous fournit également les astuces ultimes async et wait. Parce que ces deux blocs de connaissances sont relativement volumineux, nous allons en parler dans le prochain article.

Compte public personnel WeChat : si Jerry a quelque chose à dire, il publie généralement des articles techniques et des notes de lecture pour communiquer.

Tutoriel recommandé : "Tutoriel JS"

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!

Étiquettes associées:
source:jianshu.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal