async est es7. async et wait sont de nouveaux ajouts à ES7 et sont des solutions pour les opérations asynchrones?; async/await peut être considéré comme un sucre syntaxique pour les modules co et les fonctions de générateur, résolvant le code asynchrone js avec une sémantique plus claire. Comme son nom l'indique, async signifie ? asynchrone ?. Async est utilisé pour déclarer qu'une fonction est asynchrone ; il existe une règle stricte entre async et wait. Les deux sont inséparables l'un de l'autre et wait ne peut être écrit que dans des fonctions asynchrones.
L'environnement d'exploitation de ce tutoriel : système Windows 7, ECMAScript version 6, ordinateur Dell G3.
Fonctionnalités asynchrones front-end proposées dans ES7 (ES2017)?: async, wait.
Qu'est-ce que async/await ?
async et wait sont de nouveaux ajouts dans ES7 Pour les solutions aux opérations asynchrones, async/await peut être considéré comme du sucre syntaxique pour les modules co et les fonctions de générateur. Résolvez le code asynchrone js avec une sémantique plus claire.
async, comme son nom l'indique, signifie "asynchrone". async est utilisé pour déclarer qu'une fonction est asynchrone. Et wait signifie littéralement ??attendre??, qui est utilisé pour attendre l'achèvement asynchrone.
Async et wait ont une règle stricte. Les deux ne peuvent pas vivre l'un sans l'autre. Cependant, wait ne peut être écrit que dans des fonctions asynchrones.
Les étudiants qui connaissent le module co doivent savoir que le module co est un module écrit par Ma?tre TJ qui utilise une fonction génératrice pour résoudre des processus asynchrones. Il peut être considéré comme l'exécuteur de la fonction génératrice. Async/await est une mise à niveau du module co. Il possède un exécuteur de fonction de générateur intégré et ne repose plus sur le module co. Dans le même temps, async renvoie Promise.
Du point de vue ci-dessus, qu'il s'agisse du module co ou async/await, Promise est utilisé comme unité la plus basique. Les étudiants qui ne connaissent pas grand chose sur Promise peuvent d'abord en apprendre davantage sur Promise.
Comparez Promise, co, async/await
Utilisons un exemple simple pour comparer les similitudes, les différences et les compromis entre les trois méthodes.
Nous utilisons le pilote nodejs de mongodb pour interroger la base de données mongodb à titre d'exemple. La raison est que le pilote js de mongodb a implémenté le retour de Promise par défaut et nous n'avons pas besoin d'envelopper Promise séparément.
Utiliser la cha?ne de promesse
MongoClient.connect(url + db_name).then(db => { return db.collection('blogs'); }).then(coll => { return coll.find().toArray(); }).then(blogs => { console.log(blogs.length); }).catch(err => { console.log(err); })
La méthode then() de Promise peut renvoyer une autre promesse ou une valeur synchronisée. Si une valeur synchronisée est renvoyée, elle sera regroupée dans une promesse. Dans l'exemple ci-dessus, db.collection() renverra une valeur synchronisée, c'est-à-dire un objet de collection, mais elle sera enveloppée dans une promesse et sera transmise de manière transparente à la méthode then() suivante. L'exemple ci-dessus utilise une cha?ne Promise. Connectez-vous d'abord à la base de données MongoClient.connect() renvoie une promesse, puis obtenez l'objet de base de données db dans la méthode then(), puis obtenez l'objet coll et renvoyez-le. Obtenez l'objet coll dans la méthode then() suivante, puis effectuez une requête, renvoyez les résultats de la requête et appelez la méthode then() couche par couche pour former une cha?ne de promesse. Dans cette cha?ne Promise, si une exception se produit dans un lien, elle sera interceptée par le catch() final. On peut dire que ce code écrit à l'aide de la cha?ne Promise est plus élégant et le processus est plus clair que l'appel de fonctions de rappel couche par couche. Obtenez d’abord l’objet de base de données, puis l’objet de collection et enfin interrogez les données. Mais il y a ici un problème pas très "élégant", qui est que l'objet obtenu par chaque méthode then() est les données renvoyées par la méthode then() précédente. Il n’est pas accessible à travers les couches. Cela signifie que dans le troisième alors (blogs => {}), nous ne pouvons obtenir que les blogs de résultat de la requête, mais nous ne pouvons pas utiliser l'objet db et l'objet coll ci-dessus. à ce stade, que se passe-t-il si vous souhaitez fermer la base de données db.close() après avoir imprimé la liste des blogs?? à l'heure actuelle, il existe deux solutions?:
La première consiste à utiliser l'imbrication then(). Nous cassons la cha?ne Promise et la rendons imbriquée, tout comme en utilisant l'imbrication de fonctions de rappel?:
MongoClient.connect(url + db_name).then(db => { let coll = db.collection('blogs'); coll.find().toArray().then(blogs => { console.log(blogs.length); db.close(); }).catch(err => { console.log(err); }); }).catch(err => { console.log(err); })
Ici, nous imbriquons deux Promise, de sorte que lors de la dernière opération de requête, l'objet de base de données externe puisse être appelé. Toutefois, cette méthode n’est pas recommandée. La raison est simple, nous sommes passés d’un type d’enfer de fonctions de rappel à un autre type d’enfer de rappel de promesse.
De plus, nous devons détecter l'exception de chaque promesse, car la promesse ne forme pas de cha?ne.
Il existe une autre fa?on, qui consiste à passer la base de données dans chaque méthode then() :
MongoClient.connect(url + db_name).then(db => { return {db:db,coll:db.collection('blogs')}; }).then(result => { return {db:result.db,blogs:result.coll.find().toArray()}; }).then(result => { return result.blogs.then(blogs => { //注意這里,result.coll.find().toArray()返回的是一個Promise,因此這里需要再解析一層 return {db:result.db,blogs:blogs} }) }).then(result => { console.log(result.blogs.length); result.db.close(); }).catch(err => { console.log(err); });
Dans le retour de chaque méthode then(), nous combinons à chaque fois la base de données et ses autres résultats dans un retour d'objet. Veuillez noter que ce n'est pas grave si chaque résultat est une valeur synchronisée, mais s'il s'agit d'une valeur de promesse, chaque promesse nécessite une couche d'analyse supplémentaire.
Par exemple, dans l'exemple ci-dessus, le {db:result.db,blogs:result.coll.find().toArray()}
對象中,blogs
renvoyé par la deuxième méthode then() est une promesse. Dans la méthode then() suivante, nous ne pouvons pas référencer directement la valeur du tableau de la liste de blogs, nous devons donc appeler then(). méthode pour analyser d'abord une couche. Renvoyez ensuite les deux valeurs de synchronisation db et blogs. Notez que cela implique l'imbrication de Promise, mais une Promise n'imbrique qu'un seul niveau de then().
這種方式,也是很蛋疼的一個方式,因為如果遇到then()方法中返回的不是同步的值,而是Promise的話,我們需要多做很多工作。而且,每次都透傳一個“多余”的db對象,在邏輯上也有點冗余。
但除此之外,對于Promise鏈的使用,如果遇到上面的問題,好像也沒其他更好的方法解決了。我們只能根據(jù)場景去選擇一種“最優(yōu)”的方案,如果要使用Promise鏈的話。
鑒于Promise上面蛋疼的問題,TJ大神將ES6中的生成器函數(shù),用co模塊包裝了一下,以更優(yōu)雅的方式來解決上面的問題。
co搭配生成器函數(shù)
如果使用co模塊搭配生成器函數(shù),那么上面的例子可以改寫如下:
const co = require('co'); co(function* (){ let db = yield MongoClient.connect(url + db_name); let coll = db.collection('blogs'); let blogs = yield coll.find().toArray(); console.log(blogs.length); db.close(); }).catch(err => { console.log(err); });
co是一個函數(shù),將接受一個生成器函數(shù)作為參數(shù),去執(zhí)行這個生成器函數(shù)。生成器函數(shù)中使用yield
關(guān)鍵字來“同步”獲取每個異步操作的值。
上面代碼在代碼形式上,比上面使用Promise鏈要優(yōu)雅,我們消滅了回調(diào)函數(shù),代碼看起來都是同步的。除了使用co和yield有點怪之外。
使用co模塊,我們要將所有的操作包裝成一個生成器函數(shù),然后使用co()去調(diào)用這個生成器函數(shù)。看上去也還可以接受,但是ES的進(jìn)化是不滿足于此的,于是async/await被提到了ES7的提案。
async/await
我們先看一下使用async/await改寫上面的代碼:
(async function(){ let db = await MongoClient.connect(url + db_name); let coll = db.collection('blogs'); let blogs = await coll.find().toArray(); console.log(blogs.length); db.close(); })().catch(err => { console.log(err); });
我們對比代碼可以看出,async/await和co兩種方式代碼極為相似。co換成了async,yield換成了await。同時生成器函數(shù)變成了普通函數(shù)。這種方式在語義上更加清晰明了,async表明這個函數(shù)是異步的,同時await表示要“等待”異步操作返回值。
async函數(shù)返回一個Promise,上面的代碼其實是這樣:
let getBlogs = async function(){ let db = await MongoClient.connect(url + db_name); let coll = db.collection('blogs'); let blogs = await coll.find().toArray(); db.close(); return blogs; }; getBlogs().then(result => { console.log(result.length); }).catch(err => { console.log(err); })
我們定義getBlogs為一個async函數(shù),最后返回得到的博客列表最終會被包裝成一個Promise返回,如上,我們直接調(diào)用getBlogs().then()方法可獲取async函數(shù)返回值。
好了,上面我們簡單對比了一下三種解決異步方案,下面我們來深入了解一下async/await。
深入async/await
async返回值
async用于定義一個異步函數(shù),該函數(shù)返回一個Promise。
如果async函數(shù)返回的是一個同步的值,這個值將被包裝成一個理解resolve的Promise,等同于return Promise.resolve(value)
。
await用于一個異步操作之前,表示要“等待”這個異步操作的返回值。await也可以用于一個同步的值。
//返回一個Promise let timer = async function timer(){ return new Promise((resolve,reject) => { setTimeout(() => { resolve('500'); },500); }); } timer().then(result => { console.log(result); //500 }).catch(err => { console.log(err.message); });
//返回一個同步的值 let sayHi = async function sayHi(){ let hi = await 'hello world'; return hi; //等同于return Promise.resolve(hi); } sayHi().then(result => { console.log(result); });
上面這個例子返回是一個同步的值,字符串’hello world’,sayHi()是一個async函數(shù),返回值被包裝成一個Promise,可以調(diào)用then()方法獲取返回值。對于一個同步的值,可以使用await,也可以不使用await。效果效果是一樣的。具體用不用,看情況。
比如上面使用mongodb查詢博客那個例子,let coll = db.collection('blogs');
,這里我們就沒有用await,因為這是一個同步的值。當(dāng)然,也可以使用await,這樣會顯得代碼統(tǒng)一。雖然效果是一樣的。
async函數(shù)的異常
let sayHi = async function sayHi(){ throw new Error('出錯了'); } sayHi().then(result => { console.log(result); }).catch(err => { console.log(err.message); //出錯了 });
我們直接在async函數(shù)中拋出一個異常,由于返回的是一個Promise,因此,這個異常可以調(diào)用返回Promise的catch()方法捕捉到。
和Promise鏈的對比:
我們的async函數(shù)中可以包含多個異步操作,其異常和Promise鏈有相同之處,如果有一個Promise被reject()那么后面的將不會再進(jìn)行。
let count = ()=>{ return new Promise((resolve,reject) => { setTimeout(()=>{ reject('故意拋出錯誤'); },500); }); } let list = ()=>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve([1,2,3]); },500); }); } let getList = async ()=>{ let c = await count(); let l = await list(); return {count:c,list:l}; } console.time('begin'); getList().then(result => { console.log(result); }).catch(err => { console.timeEnd('begin'); console.log(err); }); //begin: 507.490ms //故意拋出錯誤
如上面的代碼,定義兩個異步操作,count和list,使用setTimeout延時500毫秒,count故意直接拋出異常,從輸出結(jié)果來看,count()拋出異常后,直接由catch()捕捉到了,list()并沒有繼續(xù)執(zhí)行。
并行
使用async后,我們上面的例子都是串行的。比如上個list()和count()的例子,我們可以將這個例子用作分頁查詢數(shù)據(jù)的場景。先查詢出數(shù)據(jù)庫中總共有多少條記錄,然后再根據(jù)分頁條件查詢分頁數(shù)據(jù),最后返回分頁數(shù)據(jù)以及分頁信息。
我們上面的例子count()和list()有個“先后順序”,即我們先查的總數(shù),然后又查的列表。其實,這兩個操作并無先后關(guān)聯(lián)性,我們可以異步的同時進(jìn)行查詢,然后等到所有結(jié)果都返回時再拼裝數(shù)據(jù)即可。
let count = ()=>{ return new Promise((resolve,reject) => { setTimeout(()=>{ resolve(100); },500); }); } let list = ()=>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ resolve([1,2,3]); },500); }); } let getList = async ()=>{ let result = await Promise.all([count(),list()]); return result; } console.time('begin'); getList().then(result => { console.timeEnd('begin'); //begin: 505.557ms console.log(result); //[ 100, [ 1, 2, 3 ] ] }).catch(err => { console.timeEnd('begin'); console.log(err); });
我們將count()和list()使用Promise.all()“同時”執(zhí)行,這里count()和list()可以看作是“并行”執(zhí)行的,所耗時間將是兩個異步操作中耗時最長的耗時。
Le résultat final est un tableau composé des résultats des deux opérations. Il nous suffit de retirer les valeurs du tableau dans l'ordre.
【Apprentissage recommandé?: Tutoriel vidéo 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!

Outils d'IA chauds

Undress AI Tool
Images de déshabillage gratuites

Undresser.AI Undress
Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover
Outil d'IA en ligne pour supprimer les vêtements des photos.

Clothoff.io
Dissolvant de vêtements AI

Video Face Swap
échangez les visages dans n'importe quelle vidéo sans effort grace à notre outil d'échange de visage AI entièrement gratuit?!

Article chaud

Outils chauds

Bloc-notes++7.3.1
éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise
Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1
Puissant environnement de développement intégré PHP

Dreamweaver CS6
Outils de développement Web visuel

SublimeText3 version Mac
Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Sujets chauds

Dans ES6, vous pouvez utiliser la méthode reverse() de l'objet tableau pour inverser le tableau. Cette méthode est utilisée pour inverser l'ordre des éléments du tableau, en pla?ant le dernier élément en premier et le premier élément en dernier. .inverse()". La méthode reverse() modifiera le tableau d'origine. Si vous ne souhaitez pas le modifier, vous devez l'utiliser avec l'opérateur d'expansion "...", et la syntaxe est "[...array].reverse(). ".

async est es7. async et wait sont de nouveaux ajouts à ES7 et sont des solutions pour les opérations asynchrones?; async/await peut être considéré comme un sucre syntaxique pour les modules co et les fonctions de générateur, résolvant le code asynchrone js avec une sémantique plus claire. Comme son nom l'indique, async signifie ? asynchrone ?. Async est utilisé pour déclarer qu'une fonction est asynchrone ; il existe une règle stricte entre async et wait. Les deux sont inséparables l'un de l'autre et wait ne peut être écrit que dans des fonctions asynchrones.

Pour la compatibilité du navigateur. En tant que nouvelle spécification pour JS, ES6 ajoute de nombreuses nouvelles syntaxes et API. Cependant, les navigateurs modernes ne prennent pas en charge les nouvelles fonctionnalités d'ES6, le code ES6 doit donc être converti en code ES5. Dans les outils de développement Web WeChat, babel est utilisé par défaut pour convertir le code de syntaxe ES6 du développeur en code ES5 bien pris en charge par les trois terminaux, aidant les développeurs à résoudre les problèmes de développement causés par différents environnements uniquement dans le projet. Il suffit de configurer et de vérifier le ; Option "ES6 à ES5".

étapes?: 1. Convertissez respectivement les deux tableaux en types d'ensemble, avec la syntaxe "newA=new Set(a); newB=new Set(b);" 2. Utilisez has() et filter() pour trouver l'ensemble de différences. , avec la syntaxe " new Set([...newA].filter(x =>!newB.has(x)))", les éléments de l'ensemble de différences seront inclus dans une collection d'ensembles et renvoyés 3. Utilisez Array. from pour convertir l'ensemble en tableau Tapez, syntaxe "Array.from(collection)".

Dans es5, vous pouvez utiliser l'instruction for et la fonction indexOf() pour réaliser la déduplication de tableau. La syntaxe "for(i=0;i<array length;i++){a=newArr.indexOf(arr[i]);if( a== -1){...}}". Dans es6, vous pouvez utiliser l'opérateur spread, Array.from() et Set pour supprimer la duplication?; vous devez d'abord convertir le tableau en un objet Set pour supprimer la duplication, puis utiliser l'opérateur spread ou la fonction Array.from(). pour reconvertir l'objet Set en un groupe Just.

Dans es6, la zone morte temporaire est une erreur de syntaxe, qui fait référence aux commandes let et const qui font que le bloc forme une portée fermée. Dans un bloc de code, avant qu'une variable ne soit déclarée à l'aide de la commande let/const, la variable est indisponible et appartient à la ? zone morte ? de la variable avant que la variable ne soit déclarée ; c'est ce qu'on appelle syntaxiquement une ? zone morte temporaire ?. ES6 stipule que la promotion des variables ne se produit pas dans les zones mortes temporaires et dans les instructions let et const, principalement pour réduire les erreurs d'exécution et empêcher l'utilisation de la variable avant qu'elle ne soit déclarée, ce qui peut entra?ner un comportement inattendu.

Dans es6, vous pouvez utiliser l'attribut length de l'objet tableau pour déterminer le nombre d'éléments dans le tableau, c'est-à-dire pour obtenir le nombre d'éléments dans le tableau, cet attribut peut renvoyer le nombre d'éléments dans le tableau ; utilisez l'instruction "array.length". Renvoie une valeur représentant le nombre d'éléments de l'objet tableau, c'est-à-dire la valeur de longueur.

L’importation ES6 entra?nera une promotion variable. Le levage de variable est le processus consistant à hisser une déclaration de variable au début de sa portée. js doit passer par les phases de compilation et d'exécution. Pendant la phase de compilation, toutes les déclarations de variables seront collectées et les variables déclarées à l'avance, tandis que les autres instructions ne changeront pas leur ordre. Par conséquent, pendant la phase de compilation, la première étape est déjà terminée. exécutée, et la deuxième partie n'est exécutée que lorsque l'instruction est exécutée dans la phase d'exécution.
