一个总是成功的jQuery承诺?

时间:2017-12-07 04:05:53

标签: javascript jquery promise

我有这个代码jQuery代码片段:

$.get('/api/' + currentPage).done(function(data) { ... })
                            .fail(...)

我希望将$.get('/api/'+currentPage)替换为始终成功的承诺,并为data返回特定值。类似的东西:

let myData = { ... }  // value of data I want to pass to the done function

(new AlwaysSucceeds(myData)).done(function(data) { ... })
                            .fail(...)

我可以拼凑一个虚拟对象,或者我可以提取出done函数,但我希望将代码的更改保持在最低限度。

有办法做到这一点吗?

更新:为了帮助澄清发生了什么,我正在使用的代码是(here)。通常这个应用程序是从一个实现/api/...调用的nodejs服务器提供的,但是我将它转换为服务 来自静态页面服务器。我知道将要归还的是什么 $.get来电。为了保持对代码的更改,我只想这样做 将该行更改为:

let myData = {...}

// $.get('/api/' + currentPage) -- comment out the $.get call
(SOMETHINGHERE(myData)).done(function(data) {

SOMETHINGHERE表达式需要实现.done(f) 它将使用f调用函数myData,然后返回 实现.fail(...)的一些对象什么都不做。

4 个答案:

答案 0 :(得分:3)

您可以使用一个函数替换$.get(...),该函数返回已使用您已有数据解析的promise。并且,获得已经解决的jQuery承诺的最短方法是使用特定值解决的:

$.when(myData).done(...)

在jQuery中使用的教科书方式越多:

$.Deferred().resolve(myData).done(...)

而且,如果您想将逻辑切换到ES6标准(而不是非标准的jQuery承诺行为),那么您可以使用它:

Promise.resolve(myData).then(...).catch(...)

答案 1 :(得分:1)

您可以通过实现AlwaysSuceeds构造函数来实现此目的。请看下面的例子。

function AlwaysSucceeds(data) {
  this.data = data; 
}

AlwaysSucceeds.prototype.done = function(fn) {
  fn(this.data);
  return this;
}

AlwaysSucceeds.prototype.fail = function(fn) {
  return this;
}


var myData = { 
  a: 1 
};

(new AlwaysSucceeds(myData)).done(function(data) { 
  console.log(data)
}).fail(function(data){ 

})

答案 2 :(得分:1)

由于jQuery Ajax函数只返回$.Deferred个对象,因此您只需替换一个立即解析的Deferred

$.Deferred().resolve(myData).then(...)

在这种特殊情况下,如果您希望在同步代码和异步代码之间轻松切换,并且可以访问async / await,则可以直接使用这些代码:

try {
    const data = await Promise.resolve($.get('/api/' + currentPage));
    // code in done
} catch (err) {
    // code in fail
}

会变成

try {
    const data = myData;
    // code in done
} catch (err) {
    // code in fail (never runs unless other code throws exceptions)
}

答案 3 :(得分:1)

目前尚不清楚你真正想要的是什么,但是使用jQuery延迟使用原生承诺,延迟有一些原生承诺没有的非标准方法。

所以为了保存,我总是假设有一个thenable,有一个then,你几乎可以随心所欲。

jQuery Deferred也不像本机承诺(取决于版本):

$.Deferred().reject("hello world")
.then(
  undefined
  ,x=>x
)
.then(
  x=>console.log("Never happens",x)
)

Promise.reject("hello world")
.then(
  undefined
  ,x=>x
);
.then(
  x=>console.log("Well behaved",x)
);

Promise.resolve().then(x=>{throw "nope"})
.then(undefined,err=>console.warn(err));

$.Deferred().resolve().then(x=>{throw "nope"})//crashes
.then(undefined,err=>err);

因此,使用原生承诺和polyfill与原生行为相似的东西将更加安全。

要回答有关未失败承诺的问题,如果您想要提出请求但在拒绝时返回默认值并在结算或拒绝后继续返回,则可以执行以下操作:

const get = (p=>{
  (url) => {
    p = p ||
    //return native promise or properly polyfilled one
    Promise.resolve($.get(url))
    .then(
      undefined,
      _=> {defaultobject:true}
    );
    return p;
  }
})();

您的get函数将返回本机承诺,因此不会faildone和其他非标准的内容。结合来自不同图书馆和本地承诺的“承诺”,最好只使用then