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

Javascript 如何在自定义函数中使用jQuery promise/deffered?,javascript,jquery,jquery-deferred,Javascript,Jquery,Jquery Deferred,我有一个通过导航器获取位置的函数。地理位置: var getLocation = function( callback ){ navigator.geolocation.getCurrentPosition( callback || function( position ){ // Stuff with geolocation }); }; 我希望能够使用jQuerys的对象来链接这个函数,但是我仍然没有掌握defered的概念和用法 我正在寻找类似于此

我有一个通过导航器获取位置的函数。地理位置:

var getLocation = function( callback ){

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

        // Stuff with geolocation

    });

};
我希望能够使用jQuerys的对象来链接这个函数,但是我仍然没有掌握defered的概念和用法

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

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

这种语法在不向后翻转并淹没在代码中的情况下是否可行?

您必须实例化一个新的延迟对象并从函数返回它(或它的承诺)。得到响应后,调用其
.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);
let runGetLocation = () => { getLocation().then( position => console.log( position ) ) }

参考


附录

getLocation().then(function(){
    drawMarkerOnMap();
});
我建议不要同时使用这两种方法,延迟对象和向函数传递回调,以保持接口简单。但如果必须保持向后兼容,只需在延迟对象上注册传递的回调:

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

尽管上面的例子确实帮了我的忙,但我还是需要多读一点书来理解这个概念

下面是一个基于我的代码的示例,其中包含一些注释,当我回到代码中时,这些注释可以帮助我,希望任何阅读此问题的人都可以使用:

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

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

使用本地语言 所有(IE11及以下版本除外)都允许您使用本机
Promise
构造

让getLocation=()=>{
返回新承诺((解决、拒绝)=>{
试一试{
navigator.geolocation.getCurrentPosition(位置=>{
解决(职位)
})
}捕捉(错误){
拒绝(错误)
}
})
};
用法:

getLocation().then(drawMarkerOnMap);
let runGetLocation = () => { getLocation().then( position => console.log( position ) ) }
您也可以使用ES2016 async/await而不是
。then()

让runGetLocation=async()=>{
试一试{
让位置=等待getLocation()
控制台日志(位置)
}catch(err){console.log(err)}
}

感谢您的回复和精彩的回答!当您说“.建议不要同时使用这两种方法、延迟对象和传递回调…”时,您如何支持异步请求,例如
getCurrentPosition
?@hitautostruct:No,我的意思是让
getLocation
接受回调并返回延迟对象。也就是说,有两种方法,要么
foo(bar)
要么
foo()。然后(bar)
。调用该函数的方法应该只有一种。如果您不使用/不需要jquery,请按照问题中的要求使用
navigator.geolocation
?否则,它可能是一段注释很好的代码,但不是答案。不,
oPromise.then(…)
并不等同于
oPromise.done().fail().always()
。最后一次回调用于事件!它甚至不等同于
oPromise.done().fail().progress()
。当知道该论点是一项承诺时,则不应使用$作为承诺的基础。