Das Problem, das Sie beschreiben, ist zweifach.
- Das von Ihnen geschriebene Programm sollte sich von außen betrachtet insgesamt asynchron verhalten .
- An der Aufrufstelle sollte nicht sichtbar sein, ob ein Funktionsaufruf die Kontrolle möglicherweise aufgibt oder nicht.
Es gibt ein paar Möglichkeiten, dies zu erreichen, aber im Grunde läuft es darauf hinaus
- mit mehreren Threads (auf einer bestimmten Abstraktionsebene)
- auf der Sprachebene mehrere Arten von Funktionen haben, die alle so genannt werden
foo(4, 7, bar, quux)
.
Für (1) fasse ich mehrere Prozesse zusammen, führe mehrere Kernel-Threads und Green-Thread-Implementierungen aus, die Threads auf Sprachlaufzeitebene für Kernel-Threads planen. Aus der Sicht des Problems sind sie gleich. In dieser Welt gibt keine Funktion jemals die Kontrolle aus der Perspektive ihres Threads auf oder verliert sie . Der Thread selbst hat manchmal keine Kontrolle und läuft manchmal nicht, aber Sie geben die Kontrolle über Ihren eigenen Thread in dieser Welt nicht auf. Ein System, das diesem Modell entspricht, kann möglicherweise neue Threads erzeugen oder vorhandene Threads verbinden. Ein System, das zu diesem Modell passt, ist möglicherweise nicht in der Lage, einen Thread wie den von Unix zu duplizierenfork
.
(2) ist interessant. Um dem gerecht zu werden, müssen wir über Einführungs- und Ausscheidungsformulare sprechen.
Ich werde zeigen, warum implizit await
nicht auf abwärtskompatible Weise zu einer Sprache wie Javascript hinzugefügt werden kann. Die Grundidee ist, dass Javascript durch die Offenlegung von Versprechungen für den Benutzer und die Unterscheidung zwischen synchronen und asynchronen Kontexten ein Implementierungsdetail preisgibt, das die einheitliche Behandlung synchroner und asynchroner Funktionen verhindert. Es gibt auch die Tatsache, dass Sie kein await
Versprechen außerhalb eines Körpers mit asynchroner Funktion geben können. Diese Entwurfswahlen sind nicht kompatibel mit "Asynchronität für den Aufrufer unsichtbar machen".
Sie können eine synchrone Funktion mit einem Lambda einführen und mit einem Funktionsaufruf beseitigen.
Einführung in die Synchronfunktion:
((x) => {return x + x;})
Synchrone Funktionsbeseitigung:
f(4)
((x) => {return x + x;})(4)
Sie können dies mit der Einführung und Beseitigung asynchroner Funktionen kontrastieren.
Einführung in die asynchrone Funktion
(async (x) => {return x + x;})
Eliminierung asynchroner Funktionen (Hinweis: Nur innerhalb einer async
Funktion gültig )
await (async (x) => {return x + x;})(4)
Das grundlegende Problem hierbei ist, dass eine asynchrone Funktion auch eine synchrone Funktion ist, die ein Versprechungsobjekt erzeugt .
Hier ist ein Beispiel für den synchronen Aufruf einer asynchronen Funktion in der node.js-Replikation.
> (async (x) => {return x + x;})(4)
Promise { 8 }
Sie können hypothetisch eine Sprache haben, auch eine dynamisch typisierte, bei der der Unterschied zwischen asynchronen und synchronen Funktionsaufrufen auf der Aufrufsite nicht sichtbar und möglicherweise auf der Definitionssite nicht sichtbar ist.
Wenn Sie eine solche Sprache auf Javascript reduzieren, müssen Sie lediglich alle Funktionen asynchronisieren.