then example done javascript jquery jquery-deferred

javascript - example - jquery then vs done



¿Cómo uso jQuery promise/deffered en una función personalizada? (3)

Tengo una función que obtiene la ubicación a través de navigator.geolocation :

var getLocation = function( callback ){ navigator.geolocation.getCurrentPosition( callback || function( position ){ // Stuff with geolocation }); };

Me gustaría hacerlo para poder encadenar esta función utilizando el objeto Apfered de Deffered pero todavía no he logrado captar el concepto y el uso de Deffered.

Estoy buscando algo similar a este pseudo código :

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

¿Es esta sintaxis incluso posible sin voltear hacia atrás y ahogarse en el código?


A pesar de que el ejemplo anterior me ayudó, tuve que leer un poco más para comprender el concepto.

A continuación se muestra un ejemplo basado en mi código que contiene comentarios que me ayudan cuando vuelvo y espero que cualquiera que lea esta pregunta de :

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


Debe crear una instancia de un nuevo objeto diferido y devolverlo (o su promesa) desde la función. Llame a su método .resolve una vez que obtenga la respuesta:

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(); };

Uso:

getLocation().then(drawMarkerOnMap);

Referencia : jQuery.Deferred

Addendum :

Recomendaría no utilizar ambos enfoques, objetos diferidos y pasar devoluciones de llamada a la función, para mantener la interfaz simple. Pero si tiene que seguir siendo compatible con versiones anteriores, simplemente puede registrar la devolución de llamada pasada en el objeto diferido:

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(); };


Sé que dice jQuery en el título, pero cuando hice esta pregunta, las promesas eran nuevas para la web y jQuery era la biblioteca de facto. Aquí hay una respuesta más moderna sin jQuery.

Usa una Promise nativa

Todos los navegadores modernos (excepto IE11 y anteriores; use un polyfill si es necesario ) le permiten usar una construcción nativa Promise .

let getLocation = () => { return new Promise( ( resolve, reject ) => { try { navigator.geolocation.getCurrentPosition( position => { resolve( position ) }) } catch ( err ) { reject( err ) } }) };

Uso:

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

También puede usar ES2016 async / .then() lugar de .then() :

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