525 Stimmen

Wie kann ich auf Promise-Auflösungsrückrufe außerhalb des Scope des Promise-Constructor-Rückrufs zugreifen?

Normalerweise wird ein Promise konstruiert und wie folgt verwendet:

new Promise((resolve, reject) => {
  const obj = new MyEventEmitter();
  obj.onsuccess = (event) => { resolve(event.result); };
  obj.onerror = (event) => { reject(event.error); };
});

Aber in letzter Zeit habe ich etwas Ähnliches wie das folgende gemacht, um den Resolver außerhalb des Executor-Callbacks flexibler zu handhaben:

let outsideResolve;
let outsideReject;
new Promise((resolve, reject) => {
  outsideResolve = resolve; 
  outsideReject = reject; 
});

Und später:

onClick = function() {
  outsideResolve();
}

Dies funktioniert gut, aber gibt es einen einfacheren Weg, dies zu tun? Wenn nicht, ist dies eine gute Praxis?

2voto

Bhargav Ponnapalli Punkte 9006

Ja, das kannst du. Verwende dazu die CustomEvent API für die Browserumgebung. Und verwende ein Event-Emitter-Projekt in Node.js-Umgebungen. Da der Abschnitt in der Frage für die Browserumgebung ist, hier ein funktionierendes Beispiel dafür.

function myPromiseReturningFunction(){
  return new Promise(resolve => {
    window.addEventListener("myCustomEvent", (event) => {
       resolve(event.detail);
    }) 
  })
}

myPromiseReturningFunction().then(result => {
   alert(result)
})

document.getElementById("p").addEventListener("click", () => {
   window.dispatchEvent(new CustomEvent("myCustomEvent", {detail : "Es funktioniert!"}))
})

 Klick mich an 

Ich hoffe, diese Antwort ist hilfreich!

0voto

jeohd Punkte 307

Ich habe eine Bibliothek namens manual-promise erstellt, die als Drop-in-Ersatz für Promise fungiert. Keine der anderen Antworten hier wird als Drop-in-Ersatz für Promise funktionieren, da sie Proxies oder Wrapper verwenden.

yarn add manual-promise

npn install manual-promise

import { ManualPromise } from "manual-promise";

const prom = new ManualPromise();

prom.resolve(2);

// actions can still be run inside the promise
const prom2 = new ManualPromise((resolve, reject) => {
    // ... code
});

new ManualPromise() instanceof Promise === true

https://github.com/zpxp/manual-promise#readme

0voto

Egor Cherniaev Punkte 9

Nur eine weitere Lösung, um ein Promise von außen aufzulösen

 class Lock {
        #lock;  // Promise, das aufgelöst werden soll (bei Freigabe)
        release;  // Lock freigeben
        id;  // Id des Locks
        constructor(id) {
            this.id = id
            this.#lock = new Promise((resolve) => {
                this.release = () => {
                    if (resolve) {
                        resolve()
                    } else {
                        Promise.resolve()
                    }
                }
            })
        }
        get() { return this.#lock }
    }

Verwendung

let lock = new Lock(... einige ID ...);
...
lock.get().then(()=>{console.log('aufgelöst/freigegeben')})
lock.release()  // Erwartet 'aufgelöst/freigegeben'

0voto

Maciej Krawczyk Punkte 11760

Ich möchte etwas anderes teilen, eine Erweiterung zu diesem Thema.

Manchmal möchten Sie, dass ein "Task-Promise" automatisch neu erstellt wird an derselben Adresse (Eigenschaft oder Variable), wenn es gelöst wird. Es ist möglich, einen externen Resolver zu erstellen, der genau das tut.

Beispiel für ein wiederkehrendes Promise mit einem externen Resolver. Immer wenn der Resolver aufgerufen wird, wird ein neues Promise an derselben Adresse/Variable/Eigenschaft erstellt.

let resolvePromise;
let thePromise;

const setPromise = (resolve) => {
  resolvePromise = () => {
    resolve();
    thePromise = new Promise(setPromise);   
  }
}
thePromise = new Promise(setPromise);

(async () => {
  let i = 0;
  while (true) {
    let msg = (i % 2 === 0) ? 'Tick' : 'Tock';
    document.body.innerHTML = msg;
    setTimeout(resolvePromise, 1000);
    await thePromise;
    i++;
  }
})();

https://jsfiddle.net/h3zvw5xr

0voto

inf3rno Punkte 22107

Ich habe eine kleine Bibliothek dafür geschrieben. https://www.npmjs.com/package/@inf3rno/promise.exposed

Ich habe den Ansatz der Factory-Methode verwendet, den andere geschrieben haben, aber ich habe auch die Methoden then, catch, finally überschrieben, sodass Sie das ursprüngliche Versprechen auch damit lösen können.

Lösen eines Versprechens ohne Executor von außen:

const promise = Promise.exposed().then(console.log);
promise.resolve("Dies sollte in der Konsole angezeigt werden.");

Rennen mit dem setTimeout des Executors von außen:

const promise = Promise.exposed(function (resolve, reject){
    setTimeout(function (){
        resolve("Ich bin fast eingeschlafen.")
    }, 100000);
}).then(console.log);

setTimeout(function (){
    promise.resolve("Ich will nicht so lange warten.");
}, 100);

Es gibt einen No-Conflict-Modus, wenn Sie den globalen Namensraum nicht verunreinigen möchten:

const createExposedPromise = require("@inf3rno/promise.exposed/noConflict");
const promise = createExposedPromise().then(console.log);
promise.resolve("Dies sollte in der Konsole angezeigt werden.");

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X