web-dev-qa-db-fra.com

Comment utiliser jQuery promise/différé dans une fonction personnalisée?

J'ai une fonction qui obtient l'emplacement via navigator.geolocation:

var getLocation = function( callback ){

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

        // Stuff with geolocation

    });

};

Je voudrais faire en sorte que je puisse chaîner cette fonction en utilisant jQuerys ' Deffered object mais je n’ai toujours pas réussi à saisir le concept et l’utilisation de Deffered.

Je cherche quelque chose de similaire à ceci Pseudo Code:

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

Cette syntaxe est-elle même possible sans basculer en arrière et noyer dans le code?

28
hitautodestruct

Je sais que jQuery est mentionné dans le titre, mais lorsque j'ai posé cette question, les promesses étaient nouvelles pour le Web et jQuery était la bibliothèque de facto. Voici une réponse plus moderne sans jQuery.

Utilisez un natif Promise

Tous les navigateurs modernes (sauf pour IE11 et inférieur; utiliser un remplissage multiple si nécessaire ) vous permettent d'utiliser une construction Promise native.

let getLocation = () => {

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

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

  })

};

Usage:

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

Vous pouvez également utiliser ES2016 async/wait au lieu de .then():

let runGetLocation = async () => {

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

}
1
hitautodestruct

Même si l'exemple ci-dessus m'a aidé, j'ai dû lire un peu plus pour comprendre le concept. 

L'exemple ci-dessous, basé sur mon code, contient des commentaires pour m'aider lorsque j'y reviens et j'espère que quiconque lira cette question Stackoverflow

/* 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
      }
);
1
Daniel Sokolowski