Javascript Promise außerhalb des Funktionsumfangs auflösen

279

Ich habe ES6 Promise verwendet.

Normalerweise wird ein Versprechen so konstruiert und verwendet

new Promise(function(resolve, reject){
    if (someCondition){
        resolve();
    } else {
        reject();
    } 
});

Aber ich habe etwas wie das Folgende getan, um die Entschlossenheit aus Gründen der Flexibilität nach draußen zu bringen.

var outsideResolve;
var outsideReject;
new Promise(function(resolve, reject) { 
    outsideResolve = resolve; 
    outsideReject = reject; 
});

Und später

onClick = function(){
    outsideResolve();
}

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

Morio
quelle
2
Ich glaube nicht, dass es einen anderen Weg gibt. Ich glaube, es ist festgelegt, dass der an übergebene Rückruf Promisesynchron ausgeführt werden muss, damit die beiden Funktionen "exportiert" werden können.
Felix Kling
1
Das funktioniert bei mir genau so, wie du es geschrieben hast. Für mich ist dies der "kanonische" Weg.
Gilad Barner
14
Ich denke, es sollte einen formellen Weg geben, um dies in Zukunft zu erreichen. Diese Funktion ist meiner Meinung nach sehr leistungsfähig, da Sie auf Werte aus anderen Kontexten warten können.
Jose
Wann immer sie eine angemessene Lösung für dieses Problem finden, hoffe ich, dass sie es auch für verschachtelte Versprechen funktionieren lassen, von denen einige möglicherweise erneut auftreten.
Arthur Tarasov
Ich denke, die Promise-API "schlägt" vor, sie immer als Rückgabewerte und niemals als Objekte zu verwenden, auf die Sie zugreifen oder die Sie aufrufen können. Mit anderen Worten, zwingen Sie uns, sie als Rückgabewerte anstelle von Objekten zu behandeln, auf die wir zugreifen können, oder Funktionen, die wir aufrufen können, oder etwas, auf das wir mit einer Variablen verweisen oder das wir als Parameter übergeben können usw. Wenn Sie Versprechen wie jedes andere Objekt verwenden, werden Sie dies wahrscheinlich tun Am Ende muss es von außen gelöst werden, wie in Ihrer Frage ... Abgesehen davon denke ich auch, dass es einen formalen Weg geben sollte, dies zu tun ... und Zurückgestellt scheint nur eine Problemumgehung für mich zu sein.
Cancerbero

Antworten:

92

Nein, es gibt keinen anderen Weg, dies zu tun - das einzige, was ich sagen kann, ist, dass dieser Anwendungsfall nicht sehr häufig ist. Wie Felix im Kommentar sagte - was Sie tun, wird konsequent funktionieren.

Es ist erwähnenswert, dass der Grund, warum sich der Versprechen-Konstruktor so verhält, die Wurfsicherheit ist. Wenn eine Ausnahme, die Sie nicht erwartet haben, auftritt, während Ihr Code im Versprechen-Konstruktor ausgeführt wird, wird dies zu einer Ablehnung, dieser Form der Wurfsicherheit - Konvertieren von geworfenen Fehlern in Ablehnungen sind wichtig und helfen dabei, vorhersehbaren Code beizubehalten.

Aus Gründen der Wurfsicherheit wurde der Versprechenskonstruktor gegenüber verzögerten Konstruktionen ausgewählt (dies ist eine alternative Versprechungskonstruktionsmethode, die das erlaubt, was Sie tun). Was Best Practices betrifft, würde ich das Element übergeben und stattdessen den Versprechungskonstruktor verwenden:

var p = new Promise(function(resolve, reject){
    this.onclick = resolve;
}.bind(this));

Aus diesem Grund - wann immer Sie können das Versprechen Konstruktor über den Export der Funktionen - Ich empfehle Ihnen , es zu verwenden. Wann immer Sie beides vermeiden können - vermeiden Sie beides und die Kette.

Beachten Sie, dass Sie den Versprechen-Konstruktor niemals für Dinge wie if(condition)das erste Beispiel verwenden sollten, das wie folgt geschrieben werden könnte:

var p = Promise[(someCondition)?"resolve":"reject"]();
Benjamin Gruenbaum
quelle
2
Hallo Benjamin! Gibt es derzeit keinen besseren Weg, um leckeren Versprechen Zucker zu bekommen, wenn wir nicht wissen, wann das Versprechen noch erfüllt wird? Wie eine Art asynchrones Warte- / Benachrichtigungsmuster ? Wie zum Beispiel "speichern" und später eine PromiseKette aufrufen ? In meinem speziellen Fall bin ich beispielsweise auf einem Server und warte auf eine bestimmte Client-Antwort (ein SYN-ACK-Handshake, um sicherzustellen, dass der Client den Status erfolgreich aktualisiert hat).
Domi
1
@Domi check out q-connection und RxJS.
Benjamin Gruenbaum
2
Wie kann ich dasselbe mit der Fetch-API tun?
Vinod Sobale
95
Nicht üblich? Am Ende brauche ich fast jedes Projekt.
Tomáš Zato - Wiedereinsetzung Monica
1
Was den Anwendungsfall betrifft, müssen Sie etwas tun, nachdem ein Ereignis ausgelöst wurde und etwas anderes passiert ist. Sie möchten ein Ereignis in ein Versprechen verwandeln und es mit einem anderen Versprechen vereinen. Scheint mir ein generisches Problem zu sein.
Gherman
130

einfach:

var promiseResolve, promiseReject;

var promise = new Promise(function(resolve, reject){
  promiseResolve = resolve;
  promiseReject = reject;
});

promiseResolve();
Fuhrmann
quelle
2
@ruX, Wie in der akzeptierten Antwort erwähnt, wurde es absichtlich so entworfen. Der Punkt ist, dass eine Ausnahme, die ausgelöst wird, vom Versprechen-Konstruktor abgefangen wird. Diese Antwort (wie auch meine) hat die Gefahr, dass möglicherweise eine Ausnahme für alle Code-Aufrufe ausgelöst wird promiseResolve(). Die Semantik eines Versprechens ist, dass es immer einen Wert zurückgibt. Dies ist auch funktional das gleiche wie der Beitrag von OP. Ich verstehe nicht, welches Problem dies auf wiederverwendbare Weise löst.
Jon Jaques
4
@ JonJaques Ich bin mir nicht sicher, ob das, was du sagst, wahr ist. Der aufrufende Code löst promiseResolve()keine Ausnahme aus. Sie können ein .catchauf dem Konstruktor definieren und unabhängig davon, welcher Code es aufruft, wird der Konstruktor .catchaufgerufen. Hier ist die jsbin zeigen , wie dies funktioniert: jsbin.com/yicerewivo/edit?js,console
carter
Ja, es ist gefangen, weil Sie einen anderen Versprechenskonstruktor darum gewickelt haben - genau den Punkt, den ich versuche zu machen. Nehmen wir jedoch an, Sie haben einen anderen Code, der löst () außerhalb des Konstruktors aufruft (auch bekannt
Jon Jaques
8
Ich bin mir nicht mal sicher, ob es ein schlechtes Design ist. Ein Fehler, der außerhalb des Versprechens geworfen wird, soll nicht innerhalb des Versprechens erfasst werden. Es ist vielleicht ein Beispiel für ein Missverständnis oder ein schlechtes Verständnis, wenn der Designer tatsächlich erwartet, dass der Fehler darin erfasst wird.
KalEl
3
Dieses genaue Konstrukt wird bereits in der Frage erwähnt. Hast du es überhaupt gelesen?
Cedric Reichenbach
103

Etwas spät zur Party hier, aber eine andere Möglichkeit wäre die Verwendung eines verzögerten Objekts. Sie haben im Wesentlichen die gleiche Menge an Boilerplate, aber es ist praktisch, wenn Sie sie weitergeben und möglicherweise außerhalb ihrer Definition auflösen möchten.

Naive Implementierung:

class Deferred {
  constructor() {
    this.promise = new Promise((resolve, reject)=> {
      this.reject = reject
      this.resolve = resolve
    })
  }
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(()=> {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(result => {
  console.log(result) // 42
})

ES5-Version:

function Deferred() {
  var self = this;
  this.promise = new Promise(function(resolve, reject) {
    self.reject = reject
    self.resolve = resolve
  })
}

function asyncAction() {
  var dfd = new Deferred()

  setTimeout(function() {
    dfd.resolve(42)
  }, 500)

  return dfd.promise
}

asyncAction().then(function(result) {
  console.log(result) // 42
})
Jon Jaques
quelle
1
Beachten Sie das lexikalische Scoping hier.
Florrie
1
Es gibt keinen praktischen Unterschied, ob resolve|rejectlexikalisch oder durch zugewiesen werden bind. Dies ist nur eine einfache Implementierung des jQuery Deferred- Objekts, das es seit 1.0 (ish) gibt. Es funktioniert genau wie ein Versprechen, außer dass es keine Wurfsicherheit gibt. Der springende Punkt dieser Frage war, wie ein paar Codezeilen beim Erstellen von Versprechungen gespeichert werden können.
Jon Jaques
1
Die Verwendung eines Aufgeschobenen ist der übliche Weg, ich habe keine Ahnung, warum dies nicht höher ist
BlueRaja - Danny Pflughoeft
1
Hervorragende Antwort! War auf der Suche nach der verzögerten Funktionalität, die jQuery bietet.
Anshul Koka
2
Ist Deferredveraltet?
Pacerier
19

Eine Lösung, die ich 2015 für mein Framework gefunden habe. Ich habe diese Art von Versprechen Aufgabe genannt

function createPromise(handler){
  var _resolve, _reject;

  var promise = new Promise(function(resolve, reject){
    _resolve = resolve; 
    _reject = reject;

    handler(resolve, reject);
  })

  promise.resolve = _resolve;
  promise.reject = _reject;

  return promise;
}

var promise = createPromise()
promise.then(function(data){ alert(data) })

promise.resolve(200) // resolve from outside
Maxmaxmaximus
quelle
4
Danke, das hat funktioniert. Aber was ist Handler? Ich musste es entfernen, damit es funktionierte.
Sahid
16

Ich mochte @ JonJaques Antwort, aber ich wollte noch einen Schritt weiter gehen.

Wenn Sie thenund catchdann das DeferredObjekt binden , implementiert es die PromiseAPI vollständig und Sie können es als Versprechen behandeln und awaites und so.

class DeferredPromise {
  constructor() {
    this._promise = new Promise((resolve, reject) => {
      // assign the resolve and reject functions to `this`
      // making them usable on the class instance
      this.resolve = resolve;
      this.reject = reject;
    });
    // bind `then` and `catch` to implement the same interface as Promise
    this.then = this._promise.then.bind(this._promise);
    this.catch = this._promise.catch.bind(this._promise);
    this[Symbol.toStringTag] = 'Promise';
  }
}

const deferred = new DeferredPromise();
console.log('waiting 2 seconds...');
setTimeout(() => {
  deferred.resolve('whoa!');
}, 2000);

async function someAsyncFunction() {
  const value = await deferred;
  console.log(value);
}

someAsyncFunction();

Rico Kahler
quelle
10

Eine Hilfsmethode würde diesen zusätzlichen Aufwand verringern und Ihnen das gleiche jQuery-Gefühl vermitteln.

function Deferred() {
    let resolve;
    let reject;
    const promise = new Promise((res, rej) => {
        resolve = res;
        reject = rej;
    });
    return { promise, resolve, reject };
}

Verwendung wäre

const { promise, resolve, reject } = Deferred();
displayConfirmationDialog({
    confirm: resolve,
    cancel: reject
});
return promise;

Welches ist ähnlich wie jQuery

const dfd = $.Deferred();
displayConfirmationDialog({
    confirm: dfd.resolve,
    cancel: dfd.reject
});
return dfd.promise();

Obwohl in einem Anwendungsfall diese einfache, native Syntax in Ordnung ist

return new Promise((resolve, reject) => {
    displayConfirmationDialog({
        confirm: resolve,
        cancel: reject
    });
});
Cory Danielson
quelle
8

Ich benutze eine Hilfsfunktion, um ein "flaches Versprechen" zu erstellen -

function flatPromise() {

    let resolve, reject;

    const promise = new Promise((res, rej) => {
      resolve = res;
      reject = rej;
    });

    return { promise, resolve, reject };
}

Und ich benutze es so -

function doSomethingAsync() {

    // Get your promise and callbacks
    const { resolve, reject, promise } = flatPromise();

    // Do something amazing...
    setTimeout(() => {
        resolve('done!');
    }, 500);

    // Pass your promise to the world
    return promise;

}

Vollständiges Arbeitsbeispiel anzeigen -

Bearbeiten: Ich habe ein NPM-Paket namens Flat-Promise erstellt und der Code ist auch auf GitHub verfügbar .

Arik
quelle
7

Sie können das Versprechen in eine Klasse einschließen.

class Deferred {
    constructor(handler) {
        this.promise = new Promise((resolve, reject) => {
            this.reject = reject;
            this.resolve = resolve;
            handler(resolve, reject);
        });

        this.promise.resolve = this.resolve;
        this.promise.reject = this.reject;

        return this.promise;
    }
    promise;
    resolve;
    reject;
}

// How to use.
const promise = new Deferred((resolve, reject) => {
  // Use like normal Promise.
});

promise.resolve(); // Resolve from any context.
Hinrich
quelle
6

Viele der Antworten hier ähneln dem letzten Beispiel in diesem Artikel . Ich speichere mehrere Versprechen zwischen, und die Funktionen resolve()und reject()können jeder Variablen oder Eigenschaft zugewiesen werden. Dadurch kann ich diesen Code etwas kompakter gestalten:

function defer(obj) {
    obj.promise = new Promise((resolve, reject) => {
        obj.resolve = resolve;
        obj.reject  = reject;
    });
}

Hier ist ein vereinfachtes Beispiel für die Verwendung dieser Version von defer(), um ein FontFaceLadeversprechen mit einem anderen asynchronen Prozess zu kombinieren :

function onDOMContentLoaded(evt) {
    let all = []; // array of Promises
    glob = {};    // global object used elsewhere
    defer(glob);
    all.push(glob.promise);
    // launch async process with callback = resolveGlob()

    const myFont = new FontFace("myFont", "url(myFont.woff2)");
    document.fonts.add(myFont);
    myFont.load();
    all.push[myFont];
    Promise.all(all).then(() => { runIt(); }, (v) => { alert(v); });
}
//...
function resolveGlob() {
    glob.resolve();
}
function runIt() {} // runs after all promises resolved 

Update: 2 Alternativen für den Fall, dass Sie das Objekt kapseln möchten:

function defer(obj = {}) {
    obj.promise = new Promise((resolve, reject) => {
        obj.resolve = resolve;
        obj.reject  = reject;
    });
    return obj;
}
let deferred = defer();

und

class Deferred {
    constructor() {
        this.promise = new Promise((resolve, reject) => {
            this.resolve = resolve;
            this.reject  = reject;
        });
    }
}
let deferred = new Deferred();
Marmelade
quelle
Wenn Sie diese Beispiele in einer asynchronen Funktion verwenden, müssen Sie auf die Versprechenseigenschaft verweisen, wenn Sie den Wert des aufgelösten Versprechens verwenden const result = await deferred.promise;
möchten
6

Akzeptierte Antwort ist falsch. Es ist ziemlich einfach, Umfang und Referenzen zu verwenden, obwohl es Promise- Puristen verärgern kann:

const createPromise = () => {
    let resolver;
    return [
        new Promise((resolve, reject) => {
            resolver = resolve;
        }),
        resolver,
    ];
};

const [ promise, resolver ] = createPromise();
promise.then(value => console.log(value));
setTimeout(() => resolver('foo'), 1000);

Wir greifen im Wesentlichen auf den Verweis auf die Auflösungsfunktion zurück, wenn das Versprechen erstellt wird, und geben dies zurück, damit es extern festgelegt werden kann.

In einer Sekunde gibt die Konsole Folgendes aus:

> foo
Ali
quelle
Ich denke, das ist der beste Ansatz. Das einzige ist, dass der Code etwas weniger ausführlich sein könnte.
Pie6k
Nett! Clevere Idee. +50 wenn ich könnte.
Utkanos
Genau das hat OP getan. Tatsächlich erfinden Sie das verzögerte Muster über Versprechen neu. Natürlich ist dies möglich und Ihr Ansatz funktioniert (als anfänglicher OP-Code), aber dies ist aufgrund des in der akzeptierten Antwort beschriebenen "Sicherheitsgrunds" nicht die beste Vorgehensweise.
Dhilt
4

Ja, du kannst. Durch Verwendung der CustomEventAPI für die Browserumgebung. Und Verwenden eines Event-Emitter-Projekts in node.js-Umgebungen. Da sich das fragliche Snippet auf die Browserumgebung bezieht, finden Sie 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 : "It works!"}))
})
<p id="p"> Click me </p>

Ich hoffe diese Antwort ist nützlich!

Bhargav Ponnapalli
quelle
3

Unsere Lösung bestand darin, Verschlüsse zum Speichern der Auflösungs- / Ablehnungsfunktionen zu verwenden und zusätzlich eine Funktion anzuhängen, um das Versprechen selbst zu erweitern.

Hier ist das Muster:

function getPromise() {

    var _resolve, _reject;

    var promise = new Promise((resolve, reject) => {
        _reject = reject;
        _resolve = resolve;
    });

    promise.resolve_ex = (value) => {
       _resolve(value);
    };

    promise.reject_ex = (value) => {
       _reject(value);
    };

    return promise;
}

Und damit:

var promise = getPromise();

promise.then(value => {
    console.info('The promise has been fulfilled: ' + value);
});

promise.resolve_ex('hello');  
// or the reject version 
//promise.reject_ex('goodbye');
Steven Spungin
quelle
2
Großartig ... Ich lerne gerade Versprechen, bin aber immer wieder verwirrt darüber, dass Sie sie anscheinend nicht "woanders" lösen können. Die Verwendung eines Verschlusses zum Ausblenden von Implementierungsdetails ist eine großartige Idee ... aber ich bin mir nicht sicher, ob Sie dies getan haben: Anstatt "pseudo" private Variablen zu haben, bin ich mir ziemlich sicher, dass es eine Möglichkeit gibt , die Variablen vollständig zu verbergen was unzugänglich sein sollte ... was wirklich ist, was Schließungen bedeuten ...
Mike Nagetier
> Ein Abschluss ist ein Codeblock, auf den beim Zugriff auf die Variablen des umschließenden Bereichs verwiesen (und der weitergegeben werden kann). var _resolve, _reject; sind der umschließende Bereich.
Steven Spungin
Ja, fair genug. Eigentlich scheint es mir, dass meine Antwort die Dinge zu kompliziert macht und dass Ihre Antwort außerdem vereinfacht werden kann: Sie müssen nur gehen promise.resolve_ex = _resolve; promise.reject_ex = _reject;... funktioniert immer noch gut.
Mike Nagetier
" Fügen Sie eine Funktion hinzu, um das Versprechen selbst zu verlängern. " - Tun Sie das nicht. Versprechen sind Ergebniswerte, sie sollten nicht die Fähigkeit bieten, sie zu lösen. Sie wollen diese erweiterten nicht weitergeben.
Bergi
2
Die Frage war, wie es außerhalb des Anwendungsbereichs gelöst werden kann. Hier ist eine Lösung, die funktioniert, und in unserer Produktion hatten wir tatsächlich einen notwendigen Grund, dies zu tun. Ich verstehe nicht, warum die Lösung des genannten Problems eine Ablehnung verdient.
Steven Spungin
2

In bestimmten Fällen fehlt mir auch das verzögerte Muster. Sie können jederzeit eine über einem ES6-Versprechen erstellen:

export default class Deferred<T> {
    private _resolve: (value: T) => void = () => {};
    private _reject: (value: T) => void = () => {};

    private _promise: Promise<T> = new Promise<T>((resolve, reject) => {
        this._reject = reject;
        this._resolve = resolve;
    })

    public get promise(): Promise<T> {
        return this._promise;
    }

    public resolve(value: T) {
        this._resolve(value);
    }

    public reject(value: T) {
        this._reject(value);
    }
}
Carsten Hess
quelle
2

Vielen Dank an alle, die in diesem Thread gepostet haben. Ich habe ein Modul erstellt, das das zuvor beschriebene Defer () -Objekt sowie einige andere darauf aufgebaute Objekte enthält. Sie alle nutzen Promises und die übersichtliche Promise-Rückrufsyntax, um die Kommunikation / Ereignisbehandlung in einem Programm zu implementieren.

  • Aufschieben: Versprechen, das aus der Ferne gelöst werden kann, fehlgeschlagen (außerhalb seines Körpers)
  • Verzögerung: Versprechen, das nach einer bestimmten Zeit automatisch aufgelöst wird
  • TimeOut: Versprechen, das nach einer bestimmten Zeit automatisch fehlschlägt.
  • Zyklus: Wieder auslösbares Versprechen, Ereignisse mit der Promise-Syntax zu verwalten
  • Warteschlange: Ausführungswarteschlange basierend auf Promise-Verkettung.

    rp = require("repeatable-promise")

    https://github.com/CABrouwers/repeatable-promise

CABrouwers
quelle
1

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

Ich habe andere den Factory - Methode Ansatz geschrieben, aber ich overrode die then, catch, finallyzu Methoden, so können Sie das ursprüngliche Versprechen von denen auch lösen.

Versprechen ohne Testamentsvollstrecker von außen lösen:

const promise = Promise.exposed().then(console.log);
promise.resolve("This should show up in the console.");

Rennen mit dem setTimeout des Testamentsvollstreckers von außen:

const promise = Promise.exposed(function (resolve, reject){
    setTimeout(function (){
        resolve("I almost fell asleep.")
    }, 100000);
}).then(console.log);

setTimeout(function (){
    promise.resolve("I don't want to wait that much.");
}, 100);

Es gibt einen konfliktfreien Modus, wenn Sie den globalen Namespace nicht verschmutzen möchten:

const createExposedPromise = require("@inf3rno/promise.exposed/noConflict");
const promise = createExposedPromise().then(console.log);
promise.resolve("This should show up in the console.");
inf3rno
quelle
1

Ich habe eine Bibliothek namens erstellt manual-promise, die als Ersatz für fungiert Promise. Keine der anderen Antworten hier funktioniert als Ersatz Promise, da sie Proxys 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

jeohd
quelle
0

Wie wäre es, eine Funktion zu erstellen, um die Zurückweisung zu entführen und zurückzugeben?

function createRejectablePromise(handler) {
  let _reject;

  const promise = new Promise((resolve, reject) => {
    _reject = reject;

    handler(resolve, reject);
  })

  promise.reject = _reject;
  return promise;
}

// Usage
const { reject } = createRejectablePromise((resolve) => {
  setTimeout(() => {
    console.log('resolved')
    resolve();
  }, 2000)

});

reject();
Nikksan
quelle
0

Ich habe eine Übersicht zusammengestellt, die diese Aufgabe erfüllt: https://gist.github.com/thiagoh/c24310b562d50a14f3e7602a82b4ef13

So sollten Sie es verwenden:

import ExternalizedPromiseCreator from '../externalized-promise';

describe('ExternalizedPromise', () => {
  let fn: jest.Mock;
  let deferredFn: jest.Mock;
  let neverCalledFn: jest.Mock;
  beforeEach(() => {
    fn = jest.fn();
    deferredFn = jest.fn();
    neverCalledFn = jest.fn();
  });

  it('resolve should resolve the promise', done => {
    const externalizedPromise = ExternalizedPromiseCreator.create(() => fn());

    externalizedPromise
      .promise
      .then(() => deferredFn())
      .catch(() => neverCalledFn())
      .then(() => {
        expect(deferredFn).toHaveBeenCalled();
        expect(neverCalledFn).not.toHaveBeenCalled();
        done();
      });

    expect(fn).toHaveBeenCalled();
    expect(neverCalledFn).not.toHaveBeenCalled();
    expect(deferredFn).not.toHaveBeenCalled();

    externalizedPromise.resolve();
  });
  ...
});
Thiagoh
quelle
0

Aktivieren Sie zuerst die Syntax --allow-natives-im Browser oder Knoten

const p = new Promise(function(resolve, reject){
    if (someCondition){
        resolve();
    } else {
        reject();
    } 
});

onClick = function () {
    %ResolvePromise(p, value)
}
Gerecht
quelle
0

Nur eine weitere Lösung, um Promise von außen zu lösen

 class Lock {
        #lock;  // Promise to be resolved (on  release)
        release;  // Release lock
        id;  // Id of lock
        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(... some id ...);
...
lock.get().then(()=>{console.log('resolved/released')})
lock.release()  // Excpected 'resolved/released'
Egor Cherniaev
quelle