Heim  >  Artikel  >  WeChat-Applet  >  Asynchrone Kapselung verbessern: Asynchrone Aufrufe mit Rückgabewerten verarbeiten – Border City Inn

Asynchrone Kapselung verbessern: Asynchrone Aufrufe mit Rückgabewerten verarbeiten – Border City Inn

hzc
hzcnach vorne
2020-06-23 10:07:232936Durchsuche
Die letzten Artikel beziehen sich auf die Entwicklung von WeChat-Miniprogrammen, daher fragte jemand: „Ich verstehe Miniprogramme nicht. Können Sie etwas anderes schreiben?“

Tatsächlich müssen Sie der Sache mit dem „kleinen Programm“ nicht allzu viel Aufmerksamkeit schenken, da „kleines Programm“ in dem Artikel nur ein Entwicklungsszenario ist. Die Probleme, die wir tatsächlich lösen, treten nicht nur in kleinen Programmen auf , und die Mittel zur Lösung des Problems sind vollständig Es hat nichts mit Miniprogrammen zu tun!

1. Problem

hinterlässt ein Problem beim asynchronen Aufruf des Proxy-Kapselungs-WeChat-Applets:

ist wie wx.request() Anleitung Diese Situation kapseln, in der es einen Rückgabewert gibt?

Wenn Sie die Anfrage während des Anfrageprozesses abbrechen müssen, wird der Rückgabewert von wx.request() verwendet:

const requestTask = wx.request(...);
if (...) {
    // 因为某些原因需要取消这次请求
    requestTask.abort();
}

Das gekapselte awx.request() gibt ein Promise-Objekt zurück, gefolgt von wx.request() Der ursprüngliche Rückgabewert hat damit nichts zu tun. Wenn Sie die Anfrage abbrechen möchten, müssen Sie den ursprünglichen Rückgabewert von wx.request() angeben.

function wxPromisify(fn) {
    return async function (args) {
        return new Promise((resolve, reject) => {
            const originalResult = fn({
//          ^^^^^^^^^^^^^^^^^^^^^^^
//          怎么把 originalResult 带出去?
                ...(args || {}),
                success: res => resolve(res),
                fail: err => reject(err)
            });
        });
    };
}

2. Alternativen

Es ist nicht zu pingelig, hier sind mehrere Optionen:

  1. Ein Objekt oder Array zurückgeben, das nach der Dekonstruktion verwendet wird . Geben Sie beispielsweise { promise, originalResult} oder [promise, originalResult] zurück. Geben Sie den Rückgabewert über einen „Container“-Parameter wie
  2. zurück und weisen Sie
  3. während der Verarbeitung einen Wert zu: awx.request(params, outBox = {}) ; outBoxoutBox.originalResultJS ist ein dynamischer Typ und kann das Promise-Objekt direkt ändern und ihm Attribute hinzufügen:
  4. .
  5. promise.originalResult = ...
  6. Aus Sicht des Benutzers wird der ursprüngliche Rückgabewert in den meisten Fällen nicht benötigt. Zu diesem Zeitpunkt möchten wir auf jeden Fall
, anstatt zuerst zu dekonstruieren und dann

(oder await awx.request() ), daher ist die erste Methode nicht optional. awaitthen()Die zweite Methode ist machbar und kann direkt verwendet werden, wenn der ursprüngliche Rückgabewert nicht benötigt wird. Wenn Sie jedoch den ursprünglichen Rückgabewert benötigen, ist dies etwas mühsam. Sie müssen zuerst ein Containerobjekt generieren und es übergeben.

Die dritte Methode sollte am unkompliziertesten zu verwenden sein. In jedem Fall wird der ursprüngliche Wert mit dem Promise-Objekt zum Vorschein gebracht, ob Sie es verwenden oder nicht, Sie können es einfach verwenden!

Nun implementieren wir die dritte Methode, die Transformation

:

wxPromisify()

3. Fehlgeschlagener Versuch

Am Anfang war es ganz einfach direkt sein

, aber jetzt sollte es ausreichen, eine temporäre Variable hinzuzufügen:

function wxPromisify(fn) {
    return async function (args) {
        const promise = new Promise((resolve, reject) => {
//      ^^^^^^^^^^^^^^^^
            promise.originalResult = fn({
//          ^^^^^^^^^^^^^^^^^^^^^^^^^
                ...(args || {}),
                success: res => resolve(res),
                fail: err => reject(err)
            });
        });
        
        return promise;
//      ^^^^^^^^^^^^^^^
    };
}
return new Promise() und dann eine Fehlermeldung zu erhalten:
TypeError: Cannot set property 'originalResult' of undefined

Dieser Fehler ist leicht zu verstehen und leicht zu beheben. . aber es ist in der Tat sehr einfach zu begehen!

Ursprünglich ging man davon aus, dass

eine lokale Variable sei, auf die direkt zugegriffen werden könne, sodass es kein Problem darstelle, sie in ihrem Unterbereich zu verwenden. Dabei wird jedoch außer Acht gelassen, dass sich dieser Subscope im Konstruktor befindet. Lassen Sie uns eine grobe Analyse durchführen:

promise

erfordert eine Funktion (die vermutlich

heißt) als Parameter, aber zu welchem ​​Zeitpunkt wird diese new Promise() ausgeführt? Beachten Sie, dass wir, nachdem factory eine Promise-Instanz generiert hat, niemals aktiv eine Methode dieser Instanz aufrufen, sodass wir daraus schließen können, dass factory während des Erstellungsprozesses ausgeführt wird. Mit anderen Worten: Die Promise-Instanz wurde zu diesem Zeitpunkt noch nicht generiert und new Promise() bezieht sich auf factory. promiseundefined

4. Erfolgreicher Versuch

Da wir nun das Problem kennen, fahren wir mit der Analyse fort.

ruft

beim Erstellen der Promise-Instanz auf und

führt factory direkt im Funktionskörper aus, und Sie können den Rückgabewert von factory sofort erhalten, also diese Promise-Instanz Konstruktion Nach Abschluss können Sie den ursprünglichen Rückgabewert erhalten. fnfnJetzt ändern wir den Code:

function wxPromisify(fn) {
    return async function (args) {
        let originalResult;
//      ^^^^^^^^^^^^^^^^^^^
        const promise = new Promise((resolve, reject) => {
            originalResult = fn({
//          ^^^^^^^^^^^^^^
                ...(args || {}),
                success: res => resolve(res),
                fail: err => reject(err)
            });
        });

        promise.originalResult = originalResult;
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        return promise;
    };
}

Wir müssen

nach

einen Wert zuweisen, und dieser „Wert“ wird dann im Prozess von new Promise() generiert Fügen Sie eine weitere lokale Variable hinzu. promise.originalResult Bringen Sie sie einfach heraus. new Promise()originalResultFertig!

5. Dinge, die lustig sind, aber ernst genommen werden sollten

Es hätte enden sollen, aber ich denke, jemand wird es tun (weil ich es in anderen Szenen gesehen habe). ):

Hinweis: Das Folgende ist ein Fehlerbeispiel!

function wxPromisify(fn) {
    return async function (args) {
        let promise = new Promise();
//      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        promise = new Promise((resolve, reject) => {
//      ^^^^^^^^^^
            promise.originalResult = fn({ ... });
//          ^^^^^^^^^^^^^^^^^^^^^^
        });

        return promise;
    };
}
Dadurch wird nicht das oben genannte
erzeugt, aber das von außen erhaltene Promise-Objekt trägt kein

. Der spezifische Grund ist derselbe wie beim oben genannten fehlgeschlagenen Versuch, daher werde ich nicht auf Details eingehen. Nur zur Erinnerung: Hier werden TypeErrorZwei Promise-Objekte originalResult generiert.

6. Lassen Sie uns noch einmal darüber sprechen

Dieses Mal wird der ursprüngliche Rückgabewert am Beispiel von wx.request() herausgebracht .abort() Methode zur Stornierungsanfrage. Dieses Anwendungsszenario ähnelt tatsächlich der Art und Weise, wie Axios mit „Stornierung“ umgeht. Sie können sich also genauso gut auf die von Axios über cancelToken implementierte Methode beziehen. Die Essenz von cancelToken ist die zweite oben erwähnte Methode – die Übergabe des „Container“-Objekts, um die benötigten Dinge herauszubringen. Das Herausbringen durch ein Promise-Objekt ist im Wesentlichen dasselbe wie das Herausbringen durch ein spezielles „Container“-Objekt, daher werde ich nicht mehr sagen.

Empfohlenes Tutorial: „WeChat Mini-Programm

Das obige ist der detaillierte Inhalt vonAsynchrone Kapselung verbessern: Asynchrone Aufrufe mit Rückgabewerten verarbeiten – Border City Inn. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:segmentfault.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen