如何以与 "when" 相同的方式处理同步和异步 jQuery promises/deferreds 并产生不同格式的结果?

How to handle both sync and async jQuery promises/deferreds the same way with "when" and results in different formats?

我知道 jQuery 有一个方法 .when() 可以异步和同步工作。

如果 .when() 传递给 jQuery promise/deffered 它将是异步的并且 .then().done() 等处理程序将传递给 promise/deferred,这将以其格式包含异步数据。

如果向 .when() 传递任何其他内容,它将是异步的,并且 .then().done() 等处理程序将传递您传递给 when 的确切对象(或任何其他内容)。

现在通常您可以自己定义同步对象,但异步对象并非总是如此,例如,异步对象可能会从某些第 3 方 Web 服务器返回。

这样做的要点是您将以某种方式转换一些数据,有时您可以使用逻辑在本地完成,但有时如果您的本地内容不能,则需要调用它自行管理。

无论哪种方式,您都会得到一个结果,您将通过回调将其传递给其余代码。

统一处理两种数据的"correct"方法是什么?

我想我可以制作我的同步对象看起来像远程服务器的对象 returns,但是 "smells bad".

或者回调中的代码可以 "sniff" 它获取的数据以查看它是哪种数据,但也 "smells bad"。

如果这看起来太简单,想象一下可能调用多个第 3 方服务器中的任何一个的情况,每个 returns 一种不同的格式。

事情是这样的:

$.when(getSyncOrAsync(7)).done(function(obj) {
  // check if 'obj' is in our format
  // check if it's in one.com's format
  // check if it's in two.com's format
  // code smell? how can we get here after normalizing the formats
  // ... or something? ...
});

function getSyncOrAsync(x) {
  if (x < 3) {
    // we can do it ourselves - return an object directly
    return { some: 'very', simple: 'object' };
  } else if (x < 6) {
    // we need to call site number one - return a promise/deferred
    return $.get('http://one.com#' + x);
  } else {
    // we need to call site number two - return a promise/deferred
    return $.get('http://two.com#' + x);
  }
}

有没有第三种方法我现在太傻了看不到?它是否涉及 promise/deferred 管道中额外步骤的诡计?这似乎效率低下但更少 "smelly"。我错过了什么?

$.get 请求上使用 .then 将结果转换为您期望的格式,以便您的承诺回调不必具有该逻辑。

getAsync(7).done(function(obj) {
  console.log(obj.some); // always works
});

function getAsync(x) {
  if (x < 3) {
    // we can do it ourselves - return a new promise resolved with object
    return $.when({ some: 'very', simple: 'object' });
  }
  if (x < 6) {
    // we need to call site number one - return a promise/deferred
    return $.get('http://one.com#' + x).then(function (result) {
      return { some: result.foo, simple: result.bar };
    });
  }
  // we need to call site number two - return a promise/deferred
  return $.get('http://two.com#' + x).then(function (result) {
    return { some: result.apple, simple: result.banana };
  });
}