20

现在我在核心文件中使用 promise.deferred。这使我能够在一个中心位置解决承诺。我一直在阅读我可能正在使用反模式,我想了解它为什么不好。

所以在我的core.js文件中,我有这样的功能:

var getMyLocation = function(location) {    
    var promiseResolver = Promise.defer();

    $.get('some/rest/api/' + location)
        .then(function(reponse) {
            promiseResolver.resolve(response);
        )}
        .catch(function(error) {
            promiseResolver.reject(error);
        });

     return promiseResolver.promise;
}

然后在我的getLocation.js文件中,我有以下内容:

var core = require('core');
var location = core.getMyLocation('Petersburg')
    .then(function(response) {
        // do something with data
    }).catch(throw error);

在阅读了 Bluebird 文档和许多关于延迟反模式的博客文章后,我想知道这种模式是否实用。我可以将其更改为以下内容:

核心.js

var getMyLocation = function(location) {
    var jqXHR = $.get('some/rest/api/' + location);
    return Promise.resolve(jqXHR)
        .catch(TimeoutError, CancellationError, function(e) {
            jqXHR.abort();
            // Don't swallow it
            throw e;
        });

获取位置.js

var location = core.getMyLocation('Petersburg')
    .then(function(response) {
        // do something
    })
    .catch(function(error) {
        throw new Error();
    });

我想我对拥有一个使用 jquery 处理 xhr 请求的中央库的最佳方式感到困惑,但 Bluebird 用于承诺。

4

2 回答 2

20

您可以调用Promise.resolvejQuery thenable 并让 Bluebird 同化它:

var res = Promise.resolve($.get(...)); // res is a bluebird Promise

您还可以直接在 Bluebird 链中返回 jQuery Promise 并让它同化它。

myBluebirdApi().then(function(){
    return $.get(...);
}).then(function(result){
    // The jQuery thenable was assimilated
});

您下面的代码很接近,但您不需要捕获TimeoutError,因为 jQuery ajax 不会抛出这些。至于捕捉取消错误。如果您希望需要取消请求,这无论如何都是您正在做的事情的最佳实践。

于 2014-06-19T20:07:20.633 回答
4

要将 thenable 转换为 Bluebird 承诺,您可以Promise.resolve像这样使用 can 调用:

var promise = Promise.resolve($.getJSON(...));

奖金部分:

大多数 JQuery AJAX 函数都是 thenable 的,但是为了您的信息,如果您想将期望回调的函数转换为 promise,您可以使用Promise.fromNode. 回调将按照err, resultNode.js 世界中的约定使用参数调用:

var promise = Promise.fromNode(function (callback) { request(url, callback); });

如果回调不期望其第一个参数出现潜在错误,您可以解决此问题:

var promise = Promise.fromNode(function (callback) {
  FB.api(url, function(response) { callback(response ? response.error : "no response", response); });
});
于 2015-08-24T17:09:35.167 回答