Bei der asynchronen Verarbeitung werden Probleme gemäß asynchronen Verfahren behandelt. Asynchrone Verarbeitung und synchrone Verarbeitung sind Gegensätze, und was sie hervorbringt, ist Multithreading oder Multiprozess. Der Vorteil der asynchronen Verarbeitung besteht darin, die Geräteauslastung zu erhöhen und dadurch die Effizienz des Programmbetriebs auf Makroebene zu verbessern. Der Nachteil besteht jedoch darin, dass es zu Konflikten bei Vorgängen und zum Lesen schmutziger Daten kommen kann. In diesem Artikel informieren wir Sie über die asynchrone Verarbeitung in JavaScript.
In der Welt von JavaScript wird der gesamte Code in einem einzigen Thread ausgeführt. Aufgrund dieses „Fehlers“ müssen alle Netzwerkvorgänge und Browserereignisse in JavaScript asynchron ausgeführt werden. Die asynchrone Ausführung kann mithilfe von Rückruffunktionen implementiert werden
Asynchrone Operationen lösen irgendwann in der Zukunft einen Funktionsaufruf aus
Zu den gängigen asynchronen Verarbeitungslösungen gehören hauptsächlich: Rückruffunktionen (CallBack), Promise und Generatorfunktionen , asynchron/warten.
1. Rückruffunktion (CallBack)
Dies ist die grundlegendste Methode der asynchronen Programmierung
Angenommen, wir haben eine getData-Methode, die zum asynchronen Abrufen von Daten verwendet wird Der erste Parameter ist die URL-Adresse der Anfrage und der zweite Parameter ist die Rückruffunktion wie folgt:
function getData(url, callBack){ // 模拟发送网络请求 setTimeout(()=> { // 假设 res 就是返回的数据 var res = { url: url, data: Math.random() } // 执行回调,将数据作为参数传递 callBack(res) }, 1000) }
Wir legen im Voraus ein Szenario fest, und zwar jeweils dreimal Die Anfrage hängt vom Ergebnis der vorherigen Anfrage ab:
getData('/page/1?param=123', (res1) => { console.log(res1) getData(`/page/2?param=${res1.data}`, (res2) => { console.log(res2) getData(`/page/3?param=${res2.data}`, (res3) => { console.log(res3) }) }) })
Wie aus dem obigen Code ersichtlich ist, lautet die URL-Adresse der ersten Anfrage: /page/1?param=123, und Das zurückgegebene Ergebnis ist res1.
Die URL-Adresse der zweiten Anfrage lautet: /page/2?param=${res1.data}, die von den res1.data der ersten Anfrage abhängt, und das zurückgegebene Ergebnis ist res2`.
Die URL-Adresse der dritten Anfrage lautet: /page/3?param=${res2.data}, die von den res2.data der zweiten Anfrage abhängt, und das zurückgegebene Ergebnis ist res3.
Da nachfolgende Anfragen vom Ergebnis der vorherigen Anfrage abhängen, können wir die nächste Anfrage nur in die Callback-Funktion der vorherigen Anfrage schreiben und so das bilden, was oft gesagt wird: die Callback-Hölle.
2. Veröffentlichen/Abonnieren
Wir gehen davon aus, dass es ein „Signalzentrum“ gibt. Wenn eine Aufgabe abgeschlossen ist, wird ein Signal an das Signalzentrum „veröffentlicht“, und andere Aufgaben können ausgeführt werden an die Signalzentrale gesendet. Die Signalzentrale „abonniert“ dieses Signal, damit sie weiß, wann sie mit der Ausführung beginnen kann. Dies wird als „Publish-Subscribe-Muster“ (Publish-Subscribe-Muster) bezeichnet, auch als „Observer-Muster“ (Observer-Muster) bekannt.
Es gibt viele Implementierungen dieses Musters. Das Folgende ist Ben Almans Tiny Pub / Sub, dies ist ein Plug-in für jQuery
Zuerst abonniert f2 „Signal Center“ jQuery erledigt „Signal
jQuery.subscribe("done", f2);
f1进行如下改写 function f1(){ setTimeout(function(){ // f1的任务代码 jQuery.publish("done"); }, 1000);} jQuery.publish("done") 的意思是, f1 执行完成后,向”信号中心 "jQuery 发布 "done" 信号,从而引发f2的执行。 此外,f2完成执行后,也可以取消订阅( unsubscribe ) jQuery.unsubscribe("done", f2);
Die Art dieser Methode ist dieselbe als „Event Listening“ Ähnlich, aber deutlich besser als Letzteres. Denn wir können den Betrieb des Programms überwachen, indem wir im „Message Center“ nachsehen, wie viele Signale vorhanden sind und wie viele Abonnenten jedes Signal hat.
3. Promise
Promise ist eine Lösung für die asynchrone Programmierung, die sinnvoller und leistungsfähiger ist als herkömmliche Lösungen – Rückruffunktionen und Ereignisse
Einfach ausgedrückt das sogenannte Promise ist ein Container, der das Ergebnis eines Ereignisses (normalerweise eines asynchronen Vorgangs) speichert, das in der Zukunft endet. Syntaktisch gesehen ist Promise ein Objekt, von dem Nachrichten für asynchrone Operationen abgerufen werden können. Promise bietet eine einheitliche API und verschiedene asynchrone Vorgänge können auf die gleiche Weise verarbeitet werden
Einfach ausgedrückt besteht die Idee darin, dass jede asynchrone Aufgabe ein Promise-Objekt zurückgibt, das über eine then-Methode verfügt, mit der Sie eine Rückruffunktion angeben können .
Jetzt verwenden wir Promise, um den obigen Fall erneut zu implementieren. Zuerst müssen wir die Methode zum asynchronen Anfordern von Daten in Promise kapseln
function getDataAsync(url){ return new Promise((resolve, reject) => { setTimeout(()=> { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) }
Dann sollte der Anforderungscode so geschrieben werden
getDataAsync('/page/1?param=123') .then(res1=> { console.log(res1) return getDataAsync(`/page/2?param=${res1.data}`) }) .then(res2=> { console.log(res2) return getDataAsync(`/page/3?param=${res2.data}`) }) .then(res3=> { console.log(res3) })
Die then-Methode gibt ein neues Promise-Objekt zurück. Der verkettete Aufruf der then-Methode vermeidet die CallBack-Hölle
Aber es ist nicht perfekt, wenn wir beispielsweise viel von then hinzufügen müssen Anweisungen, dann muss jeweils noch ein Callback geschrieben werden.
Wenn das Szenario beispielsweise komplizierter ist und jede nachfolgende Anfrage von den Ergebnissen aller vorherigen Anfragen abhängt und nicht nur von den Ergebnissen der vorherigen Anfrage, wird es komplizierter. Um es besser zu machen, wurde async/await ins Leben gerufen, um
4 zu erreichen. Die getDataAsync-Methode bleibt wie folgt unverändert >
Der Geschäftscode lautet wie folgt
function getDataAsync(url){ return new Promise((resolve, reject) => { setTimeout(()=> { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) }
}
Sie können sehen, dass die Verwendung von asyncawait genau wie das Schreiben von synchronem Code ist
Die Verwendung der Generatorfunktion kann wie folgt geschrieben werden
function getDataAsync(url){ return new Promise((resolve, reject) => { setTimeout(()=> { var res = { url: url, data: Math.random() } resolve(res) }, 1000) }) }
Dann befolgen wir dies Schritt für Schritt
var g = getData() g.next().value.then(res1=> { g.next(res1).value.then(res2=> { g.next(res2).value.then(()=> { g.next() }) }) })
上面的代码,我们逐步调用遍历器的 next() 方法,由于每一个 next() 方法返回值的 value 属性为一个 Promise 对象
所以我们为其添加 then 方法, 在 then 方法里面接着运行 next 方法挪移遍历器指针,直到 Generator 函数运行完成,实际上,这个过程我们不必手动完成,可以封装成一个简单的执行器
function run(gen){ var g = gen() function next(data){ var res = g.next(data) if (res.done) return res.value res.value.then((data) => { next(data) }) } next() }
run 方法用来自动运行异步的 Generator 函数,其实就是一个递归的过程调用的过程。这样我们就不必手动执行 Generator 函数了。 有了 run 方法,我们只需要这样运行 getData 方法
run(getData)
这样,我们就可以把异步操作封装到 Generator 函数内部,使用 run 方法作为 Generator 函数的自执行器,来处理异步。其实我们不难发现, async/await 方法相比于 Generator 处理异步的方式,有很多相似的地方,只不过 async/await 在语义化方面更加明显,同时 async/await 不需要我们手写执行器,其内部已经帮我们封装好了,这就是为什么说 async/await 是 Generator 函数处理异步的语法糖了
以上内容就是关于JavaScript中的异步处理,希望能帮助到大家。
相关推荐:
Das obige ist der detaillierte Inhalt vonAsynchrone Verarbeitungsanalyse in JavaScript. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!