代码之家  ›  专栏  ›  技术社区  ›  ErikR

一个总是成功的jQuery承诺?

  •  0
  • ErikR  · 技术社区  · 7 年前

    我有以下代码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) . 通常,该应用程序由nodejs服务器提供,该服务器实现 /api/... 呼叫,但我正在将其转换为服务 从静态页面服务器。我知道会有什么回报 这个 $.get 呼叫为了保持对代码的更改干净,我只想 将该行更改为:

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

    这个 SOMETHINGHERE 表达式需要实现 .done(f) 它将调用函数 f 具有 myData 然后返回 实现的某个对象 .fail(...) 这没什么用。

    4 回复  |  直到 7 年前
        1
  •  3
  •   jfriend00    7 年前

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

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

    在jQuery中实现这一点的更多教科书方法是:

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

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

    Promise.resolve(myData).then(...).catch(...)
    
        2
  •  1
  •   Vipin Kumar    7 年前

    您可以通过实现 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){ 
    
    })
        3
  •  1
  •   Kevin Ji    7 年前

    由于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)
    }
    
        4
  •  1
  •   HMR    7 年前

    我们不清楚您真正想要的是什么,但是使用jQuery delferred和本机承诺,delferred有一些本机承诺没有的非标准方法。

    所以为了节省我总是假设有一个 thenable ,具有 then 有了它,你几乎可以做任何你想做的事。

    jQuery延迟的行为也不像本机承诺(取决于版本):

    $.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函数将返回本机承诺,因此没有 fail , done 以及其他非标准的东西。结合不同图书馆的“承诺”和本地承诺,最好只使用 然后