Javascript 如何在自定义函数中使用 jQuery 承诺/延迟?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14377038/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 16:34:00  来源:igfitidea点击:

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

javascriptjqueryjquery-deferred

提问by hitautodestruct

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' Defferedobject 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?

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

回答by Felix Kling

You have to instantiate a new deferred object and return it (or its promise) from the function. Call its .resolvemethod 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();
};

回答by Daniel Sokolowski

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

回答by hitautodestruct

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. Here's a more modern answer without jQuery.

我知道它在标题中说 jQuery,但是当我问这个问题时,promises 对网络来说是新的,而 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 Promiseconstruct.

所有现代浏览器(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()

let runGetLocation = async () => {

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

}