jquery - 通过延迟链将变量传递给 a 并避免嵌套

jquery - Pass variables into a through a deferred chain and avoid nesting

我目前正在使用 jquery.deferred 模式为我的网站构建一个简单的灯箱,同时我正在尝试维护一个扁平的异步操作链并避免臭名昭著的厄运嵌套回调金字塔。这是我目前所拥有的:

$('#gallery a').click( function() {

    var id = $(this).attr('id');    // Id of the current selection
    var current = 0;                // Array index of the current item

    getTpl()                        // Get and load lightbox template
        .then(getData)              // Get JSON data of the selected item
        .then(getItem)              // Pass JSON data and get the item
        .then(loadItem)             // Use JSON data to create the HTML output
        .done(function() {
            // Wrap everything up, intialize the lightbox controls
            // (requires the JSON data) and load the lightbox
        });
});

前两个步骤(getTpl、getData)很简单 AJAX 承诺并且工作正常。我还可以将 JSON 数据进一步向下传递到第三步 (getItem)。这就是问题开始的地方:

  1. 我必须将变量 'id' 和 'current' 从较高范围传递到链中调用的函数(getItem 和 loadItem 使用这些变量来构造 URL 并创建 HTML 输出)。如何在不破坏异步链的情况下做到这一点?
  2. 我真的必须 return 来自每个函数的 JSON 数据(和其他变量)才能在链中进一步使用它吗?有没有更简单的方法来保持数据和必要的变量在整个链中可用?
  3. 我可以将随机操作放入链中吗?一个简单的 jquery 淡入?这就是 '.done' 的用途,因为 '.then' 需要一个新的承诺,对吗?

提前致谢!

如果你这样做:

var id = $(this).attr('id');    // Id of the current selection
var current = 0;                // Array index of the current item

getTpl()                        // Get and load lightbox template
    .then(getData)              // Get JSON data of the selected item
    .then(getItem)              // Pass JSON data and get the item
    .then(loadItem)

然后,您将把它留给承诺系统来为链中的下一个函数设置参数。由于 promise 系统将使用链中先前操作的 return ,如果你想将参数传递给所有这些,那么所有函数都必须参与传递它们。有了这个确切的结构,就没有办法绕过它了。

有关与链共享数据的更通用方法,请参阅:

像这样传递任意数量的变量的常见方案是将它们放在一个对象上,让每个函数接受和对象以及 return 该对象。

var options = {
    id: $(this).attr('id'),     // Id of the current selection
    current: 0                  // Array index of the current item
};

getTpl(options)                 // Get and load lightbox template
    .then(getData)              // Get JSON data of the selected item
    .then(getItem)              // Pass JSON data and get the item
    .then(loadItem)

然后,每个函数 getTpl()getData()getItem()loadItem() 可以期望它们的第一个参数是这个选项对象,它们都应该用那个选项解析目的。他们每个人都可以自由地将新属性添加到将通过链传递的对象上。


对于如何构建它,您确实有一些其他选择。如果你的函数是内联的,那么它们可以直接访问范围内的部分变量:

var id = $(this).attr('id');    // Id of the current selection
var current = 0;                // Array index of the current item

getTpl()                        // Get and load lightbox template
    .then(function() {
        // code here can directly access current and id variables
    }).then(...)

或者,您可以直接调用您的函数并传递它们需要的任何变量:

var id = $(this).attr('id');    // Id of the current selection
var current = 0;                // Array index of the current item

getTpl()                        // Get and load lightbox template
    .then(function() {
        return getData(id, current);
    }).then(function(data) {
        return getItem(data, id);
    }).then(function(item) {
        return loadItem(item, current);
    });