简体   繁体   English

如何在自定义函数中使用jQuery promise / deffered?

[英]How do I use jQuery promise/deffered in a custom function?

I have a function that gets the location through navigator.geolocation : 我有一个通过navigator.geolocation获取位置的函数:

var getLocation = function( callback ){

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

        // Stuff with geolocation

    });

};

I would like to make it so that I could chain this function using jQuerys' Deffered object but I have still not managed to grasp the concept and usage of Deffered. 我想使它这样我就可以用链jQuerys'这个功能递延对象,但我仍然没有成功地把握递延的概念和使用方法。

I'm looking for something similar to this Pseudo Code : 我正在寻找类似于这个伪代码的东西:

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

Is this syntax even possible without flipping over backwards and drowning in code? 这种语法是否可以在不向后翻转并在代码中淹没的情况下实现?

You have to instantiate a new deferred object and return it (or its promise) from the function. 您必须实例化一个新的延迟对象并从该函数返回它(或它的promise)。 Call its .resolve method once you get the response: 获得响应后调用其.resolve方法:

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

Usage: 用法:

getLocation().then(drawMarkerOnMap);

Reference : jQuery.Deferred 参考jQuery.Deferred


Addendum : 附录

I would advise against using both approaches, deferred objects and passing callbacks to the function, to keep the interface simple. 我建议不要使用两种方法,延迟对象和将回调传递给函数,以保持界面简单。 But if you have to stay backwards compatible, you can simply register the passed callback at the deferred object: 但是如果你必须保持向后兼容,你可以简单地在延迟对象上注册传递的回调:

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

Even though the above example did help me I had to do a bit more reading to wrap my head around the concept. 尽管上面的例子对我有所帮助,但我不得不做更多的阅读来围绕这个概念。

Below is example based on my code that contains comments to assist me when I come back to it and hopefully anyone reading this Stackoverflow 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
      }
);

I know it says jQuery in the title but when I asked this question promises were new to the web and jQuery was the de facto library. 我知道它在标题中说jQuery但是当我问这个问题时,承诺对于网络而言是新的,jQuery是事实上的库。 Here's a more modern answer without jQuery. 这是没有jQuery的更现代的答案。

Use a native Promise 使用本机Promise

All modern browsers (except for IE11 and below; use a polyfill if needed ) enable you to use a native Promise construct. 所有现代浏览器 (IE11及以下版本除外; 如果需要使用polyfill )使您可以使用本机Promise构造。

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

You can also use ES2016 async/await instead of .then() : 您也可以使用ES2016 async / await而不是.then .then()

let runGetLocation = async () => {

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM