【问题标题】:How do I use jQuery promise/deffered in a custom function?如何在自定义函数中使用 jQuery 承诺/延迟?
【发布时间】:2013-01-17 10:32:22
【问题描述】:

我有一个通过navigator.geolocation获取位置的函数:

var getLocation = function( callback ){

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

        // Stuff with geolocation

    });

};

我想做它,以便我可以使用 jQuerys 的 Deffered 对象链接这个函数,但我仍然没有设法掌握 Defered 的概念和用法。

我正在寻找类似于此伪代码的东西:

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

这种语法甚至可以在不向后翻转和淹没在代码中的情况下实现吗?

【问题讨论】:

    标签: javascript jquery jquery-deferred


    【解决方案1】:

    您必须实例化一个新的延迟对象并从函数中返回它(或其承诺)。收到响应后调用其.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();
    };
    

    用法:

    getLocation().then(drawMarkerOnMap);
    

    参考jQuery.Deferred


    附录

    我建议不要同时使用这两种方法,即延迟对象和将回调传递给函数,以保持界面简单。但是如果你必须保持向后兼容,你可以简单地在延迟对象上注册传递的回调:

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

    【讨论】:

    • 感谢您的回复和精彩的回答!当您说“..建议不要同时使用这两种方法、延迟对象和传递回调..”时,您还能如何支持异步请求,例如 getCurrentPosition
    • @hitautodestruct:不,我的意思是让getLocation 接受回调返回一个延迟对象。 IE。有两种方法,foo(bar)foo().then(bar)。应该只有一种方法可以调用该函数。
    • 如果你不使用/不需要jquery,看看this answer
    【解决方案2】:

    尽管上面的示例确实对我有所帮助,但我还是需要多阅读一些内容才能理解这个概念。

    下面是基于我的代码的示例,其中包含 cmets 以在我回到它时为我提供帮助,希望任何阅读此 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
          }
    );
    

    【讨论】:

    • 您能按照问题中的要求使用navigator.geolocation 吗?否则,它可能是一段注释很好的代码,但不是答案
    • 不,oPromise.then(…)等同于oPromise.done().fail().always()。最后一个回调是针对progress 事件!
    • 而且它甚至不等同于oPromise.done().fail().progress()then method 是 Promise 的 monadic functionality 的基础
    • 请注意,当您知道参数是一个承诺时,您不应该使用$.when
    【解决方案3】:

    我知道它在标题中提到了 jQuery,但是当我问这个问题时,承诺对网络来说是新的,而 jQuery 是事实上的库。这是一个没有 jQuery 的更现代的答案。

    使用原生Promise

    所有modern browsers(IE11 及以下版本除外;use a polyfill if needed)都允许您使用本机Promise 构造。

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

    用法:

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

    你也可以使用 ES2016 async/await 代替.then()

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

    【讨论】:

      猜你喜欢
      • 2015-03-27
      • 2023-03-21
      • 1970-01-01
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      相关资源
      最近更新 更多