0Pricing
jQuery Academy · 课时

串联与组合 Promise

学习使用 .then() 和 .pipe() 串联多个异步操作,并通过 $.when() 等待多个 Promise 完成,以组合复杂的工作流。

串联与组合 Promise 是 CoddyKit 上的免费 jQuery Academy 课时。 这是第 2 节课,共 3 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 jQuery Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 jQuery Academy 课程共包含 3 节课。

按顺序执行异步操作

在 Web 开发中,我们经常需要按照特定顺序执行异步任务(例如获取数据)。链接 Promise 可以让我们整洁地完成这项工作。

回调嵌套容易导致“回调地狱”,而我们可以改为按顺序连接各个操作,使代码更易于阅读和维护。

使用 .then() 进行链接

.then() 方法是实现链接的基础。当 Deferred(或 Promise)得到解决时,其 .then() 回调会执行。该回调返回的内容随后可以供链接中的下一个 .then() 使用。

如果回调返回一个新的 Deferred,链接会等待这个新的 Deferred 得到解决后再继续。

简单的 .then() 链示例

下面来看一个简单示例,其中我们模拟两个异步步骤。第二个步骤仅在第一个步骤完成后运行,并且会使用第一个步骤中的数据。

请注意,step1 的结果('Data from Step 1')会传递给 step2。

function runChainExample() {
  let dfd1 = new $.Deferred();
  let dfd2 = new $.Deferred();

  setTimeout(() => {
    console.log("Step 1 complete!");
    dfd1.resolve("Data from Step 1");
  }, 500);

  dfd1.then(function(data1) {
    console.log("Received in Step 2: " + data1);
    setTimeout(() => {
      console.log("Step 2 complete!");
      dfd2.resolve("Processed " + data1);
    }, 300);
    return dfd2;
  }).then(function(data2) {
    console.log("Received in Final Step: " + data2);
    console.log("Chain finished!");
  });
}

$(document).ready(function() {
  runChainExample();
});

.then() 链中的数据流

.then() 回调返回的值决定了下一个 .then() 的输入。

  • 如果返回非 Deferred 值,该值就会成为下一个 .then() 的已解决值。
  • 如果返回一个 Deferred 对象,链接会暂停,直到该 Deferred 得到解决,然后将其已解决的值传递给下一个 .then()。

使用 .pipe() 进行转换

虽然 .then() 是现代标准,但 jQuery 的 .Deferred() 也提供了 .pipe()。它与 .then() 类似,但最初设计用于转换已解决值或已拒绝值,或者筛选出继续执行链接的 Deferred。

.pipe() 可以返回一个新的 Deferred,该 Deferred 会以转换后的值得到解决,从而有效地将该值“传输”到下一个阶段。

.pipe() 转换示例

在这里,我们使用 .pipe() 获取第一个操作的结果,将其转换(例如转换为大写),然后把转换后的值传递给最终的 .done() 处理程序。

function runPipeExample() {
  let dfd = new $.Deferred();

  setTimeout(() => {
    console.log("Initial data ready.");
    dfd.resolve("hello world");
  }, 500);

  dfd.pipe(function(originalData) {
    console.log("Piping: Transforming data...");
    return originalData.toUpperCase(); // Transforms the value
  }).done(function(transformedData) {
    console.log("Final result: " + transformedData);
  });
}

$(document).ready(function() {
  runPipeExample();
});

使用 $.when() 进行组合

如果您有多个相互独立的异步任务,但需要等待所有任务完成后才能继续,该怎么办?这正是 $.when() 的用武之地。

$.when() 接受一个或多个 Deferred 对象(或 Promise)作为参数,并返回一个新的 Deferred。只有当所有输入 Deferred 都得到解决时,这个新的 Deferred 才会得到解决。

$.when() 并行任务示例

在本示例中,我们模拟两个相互独立的 AJAX 请求(fetchUser 和 fetchPosts)。我们使用 $.when() 等待两者完成,然后记录组合后的结果。

请注意,它们是并行运行的,而不是按顺序运行。

function runWhenExample() {
  function fetchUser() {
    let dfd = new $.Deferred();
    setTimeout(() => {
      console.log("User data fetched.");
      dfd.resolve({ id: 1, name: "Alice" });
    }, 800);
    return dfd.promise();
  }

  function fetchPosts() {
    let dfd = new $.Deferred();
    setTimeout(() => {
      console.log("Posts data fetched.");
      dfd.resolve([{ id: 101, title: "Post 1" }, { id: 102, title: "Post 2" }]);
    }, 500);
    return dfd.promise();
  }

  $.when(fetchUser(), fetchPosts())
    .done(function(userData, postsData) {
      console.log("All data loaded!");
      console.log("User: ", userData);
      console.log("Posts: ", postsData);
    })
    .fail(function() {
      console.log("One or more tasks failed.");
    });
}

$(document).ready(function() {
  runWhenExample();
});

访问 $.when() 的结果

当 $.when() 返回的 Deferred 得到解决时,其 .done() 或 .then() 回调会按照输入 Deferred 传入 $.when() 的顺序,以单独的参数接收各个输入 Deferred 的已解决值。

这样一来,所有数据都可用后,就能轻松组合并处理来自多个来源的数据。

Promise 链测验

请考虑以下 jQuery 代码片段:

let dfd1 = new $.Deferred();
let dfd2 = new $.Deferred();

dfd1.then(function(val) {
  return val + " World";
}).then(function(newVal) {
  console.log(newVal); // Line A
  return dfd2;
}).then(function() {
  console.log("Finished!"); // Line B
});

dfd1.resolve("Hello");
dfd2.resolve();

控制台最终会输出什么内容,输出顺序又是怎样的?

回顾:链接与组合

我们已经学习了如何管理复杂的异步工作流:

  • 使用 .then() 进行链接:按顺序执行操作,将结果从一个阶段传递到下一个阶段。
  • .pipe():一种较早的方法,用于在链接中转换值或映射 Deferred。
  • 使用 $.when() 进行组合:等待多个相互独立的 Deferred 并行完成后再继续,并将它们的结果作为单独的参数提供。

这些模式对于构建可靠且易读的异步应用至关重要。

常见问题解答

「串联与组合 Promise」课时是免费的吗?

是的 — 「串联与组合 Promise」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 jQuery Academy 课程的其余内容,请升级到 CoddyKit PRO。 jQuery Academy 课程共包含 3 节课。

「串联与组合 Promise」这节课中我会学到什么?

学习使用 .then() 和 .pipe() 串联多个异步操作,并通过 $.when() 等待多个 Promise 完成,以组合复杂的工作流。 你通过在浏览器中直接运行的动手代码来练习 jQuery Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 jQuery Academy 需要有经验吗?

无需任何先前经验。CoddyKit 上的 jQuery Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 3 节。

「串联与组合 Promise」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 jQuery Academy 课中编写并运行代码吗?

能。每节 jQuery Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 理解 Deferred 对象
  2. 串联与组合 Promise
  3. 处理多个异步任务
← 返回 jQuery Academy