Wie verwende ich jQuery Promise/Deffered in einer benutzerdefinierten Funktion?

Lesezeit: 4 Minuten

Ich habe eine Funktion, die den Standort durch bekommt navigator.geolocation:

var getLocation = function( callback ){

    navigator.geolocation.getCurrentPosition( callback || function( position ){

        // Stuff with geolocation

    });

};

Ich möchte es so machen, dass ich diese Funktion mit jQuerys verketten könnte. Aufgeschoben Objekt, aber ich habe es immer noch nicht geschafft, das Konzept und die Verwendung von Deffered zu verstehen.

Ich suche sowas ähnliches Pseudo-Code:

getLocation().then(function(){
    drawMarkerOnMap();
});

Ist diese Syntax überhaupt möglich, ohne rückwärts umzudrehen und im Code zu ertrinken?

Benutzer-Avatar
Felix Klinge

Sie müssen ein neues verzögertes Objekt instanziieren und es (oder sein Versprechen) von der Funktion zurückgeben. Nennen Sie es .resolve Methode, sobald Sie die Antwort erhalten:

var getLocation = function() {
    var deferred = new $.Deferred();

    navigator.geolocation.getCurrentPosition(function( position ){
        // Stuff with geolocation
        deferred.resolve(position);
    });

    // return promise so that outside code cannot reject/resolve the deferred
    return deferred.promise();
};

Verwendungszweck:

getLocation().then(drawMarkerOnMap);

Bezug: jQuery.Deferred


Nachtrag:

Ich würde davon abraten, beide Ansätze zu verwenden, verzögerte Objekte und Rückrufe an die Funktion zu übergeben, um die Schnittstelle einfach zu halten. Aber wenn Sie abwärtskompatibel bleiben müssen, können Sie den übergebenen Callback einfach am zurückgestellten Objekt registrieren:

var getLocation = function(callback) {
    var deferred = new $.Deferred();

    if ($.isFunction(callback)) {
        deferred.then(callback);
    }

    navigator.geolocation.getCurrentPosition(function( position ){
        // Stuff with geolocation
        deferred.resolve(position);
    });

    // return promise so that outside code cannot reject/resolve the deferred
    return deferred.promise();
};

  • Vielen Dank für die Antwort und fantastische Antwort! Wenn Sie sagen “.. Ratschlag gegen die Verwendung beider Ansätze, verzögerter Objekte und Weiterleitung von Rückrufen …”, wie würden Sie sonst eine asynchrone Anforderung wie unterstützen getCurrentPosition?

    – hitautodestruct

    17. Januar 2013 um 11:19 Uhr

  • @hitautodestruct: Nein, was ich meinte, ist zu haben getLocation Rückruf annehmen und gibt ein zurückgestelltes Objekt zurück. Dh es gäbe auch zwei Möglichkeiten foo(bar) oder foo().then(bar). Es sollte nur eine Möglichkeit geben, diese Funktion aufzurufen.

    – Felix Klinge

    17. Januar 2013 um 11:28 Uhr

  • Sehen Sie sich diese Antwort an, wenn Sie jquery nicht verwenden/benötigen

    – hitautodestruct

    20. März 2019 um 8:20 Uhr

Benutzer-Avatar
Daniel Sokolowski

Obwohl mir das obige Beispiel geholfen hat, musste ich etwas mehr lesen, um das Konzept zu verstehen.

Unten ist ein Beispiel, das auf meinem Code basiert und Kommentare enthält, die mir helfen, wenn ich darauf zurückkomme, und hoffentlich jeder, der diese Stackoverflow-Frage liest:

/* promise based getFilter to accommodate getting surrounding suburbs */
oSearchResult.fPromiseOfFilterSetting = function fPromiseOfFilterSetting(sId) {
    var self = this;
    self.oPromiseCache = self.oPromiseCache || {}; // creates a persistent cache 
                                                   // across function calls
    var oDeferred = $.Deferred(); // `new` keyword is optional
    var oPromise = oDeferred.promise();

    // leverage the cache (it's ok if promise is still pending), you can key
    if (self.oPromiseCache[sId] !== undefined) {
        return self.oPromiseCache[sId];
    }
    else {
        self.oPromiseCache[sId] = oPromise;
    }

    // do our asynchronous action below which at some point calls
    // defered.resolve(...) and hence complete our promise
    $.cmsRestProxy.doAjaxServiceRequest('ocms_searchProperties_Extension', {
        action : 'getSurroundingSuburbs',
        sSuburbIds : 'a0RO0000003BwWeMAK'
    }, function(result, json) {
        console.log("doAjaxServiceRequest(
                       'ocms_searchProperties_Extension')", json);
        oDeferred.resolve(json); // `json` is our result and `.resolve(json)` 
                                 // passes the value as first argument to 
                                 // the `oPromise.done`, `oPromise.fail` 
                                 // and `oPromise.always` callback functions
    })

    // We can now return the promise or attach optional `oPromise.done`,
    // `oPromise.fail`, and `oPromise.always` callbacks which will execute first
    // in the chain.
    //
    // Note that `oPromise.then(doneCallback, failCallback, alwaysCallback)`
    // is short form for the below
    oPromise.done(function(value) { // returned by promise.resolve(...); call
        console.log('will run if this Promise is resolved.', value);
    })
    oPromise.fail(function(value) {
        console.log("will run if this Promise is rejected.", value);
    });
    oPromise.always(function(value) {
        console.log("this will run either way.", value);
    });

    // return a promise instead of deferred object so that
    // outside code cannot reject/resolve it
    return oPromise;
}

// then to use one would do
oSearchResult.fPromiseOfFilterSetting().done(function(value) {alert(value)});

// or using $.when chaining
$.when(
    oSearchResult.fPromiseOfFilterSetting()
)
.done(
      function fDoneCallback(arg1, arg2, argN) {
          console.debug(arguments) // `arguments` is an array of all args collected
      }
);

  • Können Sie bitte die verwenden navigator.geolocation wie in der Frage gestellt? Andernfalls könnte es sich um ein schön kommentiertes Stück Code handeln, aber nicht um ein Antworten.

    – Bergi

    15. Juli 2014 um 3:23 Uhr

  • Nein, oPromise.then(…) ist nicht gleichwertig oPromise.done().fail().always(). Der letzte Rückruf ist für Fortschritt Veranstaltungen!

    – Bergi

    15. Juli 2014 um 3:25 Uhr

  • Und es ist nicht einmal gleichbedeutend mit oPromise.done().fail().progress(). Das then Methode ist die Grundlage für die monadische Funktionalität von Promises

    – Bergi

    15. Juli 2014 um 3:27 Uhr

  • Beachten Sie, dass Sie nicht verwenden sollten $.when wenn Sie wissen, dass das Argument ein Versprechen ist.

    – Bergi

    15. Juli 2014 um 3:28 Uhr

Ich weiß, dass im Titel jQuery steht, aber als ich diese Frage stellte, waren die Versprechungen neu im Web und jQuery war die De-facto-Bibliothek. Hier ist eine modernere Antwort ohne jQuery.

Verwenden Sie einen Einheimischen Promise

Alle moderne Browser (außer IE11 und darunter; Verwenden Sie bei Bedarf eine Füllwatte) ermöglichen es Ihnen, eine native zu verwenden Promise konstruieren.

let getLocation = () => {

  return new Promise( ( resolve, reject ) => {

    try {
      navigator.geolocation.getCurrentPosition( position => {
        resolve( position )
      })
    } catch ( err ) {
      reject( err )
    }

  })

};

Verwendungszweck:

let runGetLocation = () => { getLocation().then( position => console.log( position ) ) }

Sie können stattdessen auch ES2016 async/await verwenden .then():

let runGetLocation = async () => {

  try {
    let position = await getLocation()
    console.log( position )
  } catch ( err ) { console.log( err ) }

}

1226660cookie-checkWie verwende ich jQuery Promise/Deffered in einer benutzerdefinierten Funktion?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy