链接推迟

时间:2013-07-30 11:56:35

标签: jquery jquery-deferred deferred

我有很多功能,目前看起来像这样:

function LoadFromURL(url) 
{
    var d = $.Deferred();
    $.get(url).then(function(text)
    {
        LoadFromText(text).then(function(obj)
        {
            d.resolve(obj);
        }, 
        function(err)
        {
            d.reject(err);
        });
    }, 
    function(err)
    {
        d.reject(err);
    });
    return d.promise();
}

此函数接受一个URL并在promise中加载文本。然后将文本传递给LoadFromText函数,该函数返回另一个promise。如果成功,则解决外部延迟。如果无法加载URL,或者LoadFromText函数失败,则拒绝外部延迟。

有没有办法可以将解决/拒绝的结果链接起来并最终得到这样的结果:

function LoadFromURL(url) 
{
    return $.get(url).then(function(text)
    {
        return LoadFromText(text);
    }, 
    function(err)
    {
        return $.Deferred().reject(err);
    }).promise();
}

我已经看到一些承诺的实现允许这样做 - 在'then'中返回一个promise,意味着使用了promise的最终结果。

我意识到这暂时不起作用(结果是承诺,而不是承诺的结果),但希望有人可以建议一种方法来完成这项工作,这样我就可以整理有时令人困惑的混乱第一个例子。

我希望这是有道理的。感谢。

3 个答案:

答案 0 :(得分:1)

  

有没有办法可以将结果链接

是的,这是then的默认行为!

function LoadFromURL(url) {
    return $.get(url).then(LoadFromText);
}
  

我已经看到一些承诺的实现允许这样做 - 在'then'中返回一个promise,意味着使用了promise的最终结果。

自1.8版以来,

jQuery 支持此行为。对于1.5到1.7,您可以使用.pipe

答案 1 :(得分:0)

LoadFromURL将简化如下:

function LoadFromURL(url) {
    return $.get(url).then(function(text) {
        return LoadFromText(text);
    });
}

可能存在您未考虑过的问题......

与原始版本一样,该过程将倾向于无限递归,直到服务器返回HTTP错误。在适当地编写服务器资源时会遇到轻微的挑战,特别是如果可能需要访问最终提供的文本。

稍微考虑一下,您可以以文本本身或HTTP响应代码中指示“继续”或“完成”的方式传递所有文本。例如,您可以使用响应代码202(“已接受”)来指示该过程不完整。

我认为这会有效(使用jQuery 1.5+):

function LoadFromURL(url) {
    return $.get(url).then(function(text, textStatus, jqXHR) {
        if(jqXHR.status === 202) {//continue
            return LoadFromText(text);
        }
        else {//complete
            return text;
        }
    });
}

您只需要安排服务器返回202表示“继续”或200表示“完成”。

因此,可以按如下方式调用LoadFromURL():

LoadFromURL('my/resource').then(function(text) {
    console.log("After a series of $.get requests, the finally delivered text was:\n" + text);
});

答案 2 :(得分:0)

我不确定我是否理解正确,因为你的第二个功能LoadFromText对我来说是某种黑盒子。不过,我认为你的构造对于执行的事情来说太过臃肿了。尝试在更少的功能中执行此操作。我做了一个命题:

function Load() {
    var myUrl = '//path.to/url';
    LoadFromUrl(myUrl)
        .then(LoadFromText, errorHandler)
        .then(successHandler, errorHandler);
}

function successHandler(returnedData) {
    console.log('Requests were successful: ' + returnedData);
}

function errorHandler(err) {
    console.log('An error occurded: ' + err);
}

function LoadFromURL(url) {
    return $.get(url);
}

function LoadFromText(text) {
    // THIS IS SOME SORT OF BLACK BOX FOR ME...
    // SEEMS TO RETURN A PROMISE, THOUGH

    var $deferred = $.Deferred();

    // DO THE LOGIC TO EITHER REJECT OR RESOLVE THE PROMISE

    return $deferred.promise();
}

您只使用主函数Load来启动ajax链。第一个ajax请求完成后,第二个以第一个ajax请求的数据开始。之后,successHandler将对第二个ajax调用的数据执行任何操作。这是您解决方案的重要补充 除此之外,它与您所做的基本相同,但分发给更易于维护的小功能。