1

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

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 函数,该函数返回另一个承诺。如果成功,则外部延迟被解决。如果无法加载 URL,或者 LoadFromText 函数失败,则外部延迟被拒绝。

有没有一种方法可以链接解决/拒绝的结果并最终得到如下结果:

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

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

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

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

4

3 回答 3

1

有没有办法可以链接结果

是的,这是then!

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

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

jQuery从 1.8 版开始支持这种行为对于 1.5 到 1.7,您可以使用.pipe.

于 2013-07-31T21:37:19.747 回答
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);
});
于 2013-07-31T20:38:40.527 回答
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();
}

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

于 2013-07-31T21:05:00.310 回答