如何转换jQuery $.ajax调用蓝鸟承诺没有延迟的反模式

How to cast jQuery $.ajax calls to Bluebird promises without the deferred anit-pattern

本文关键字:承诺 蓝鸟 延迟 模式 调用 ajax 何转换 转换 jQuery      更新时间:2023-09-26

现在我在核心文件中使用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文档和许多关于延迟反模式的博客文章之后,我想知道这个模式是否实用。我可以将其更改为以下内容:

core.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;
        });

getLocation.js

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

我想我很困惑,什么是最好的方法有一个中央库处理xhr请求使用jquery调用,但蓝鸟的承诺。

你可以在jQuery中调用Promise.resolve并让Bluebird吸收它:

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

你也可以直接在Bluebird链中返回jQuery承诺,并让它吸收它。

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

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

要将thenable转换为Bluebird promise,您可以使用can调用Promise.resolve,如下所示:

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

奖金部分:

大多数JQuery AJAX函数都是启用的,但是对于你的信息,如果你想转换一个函数,期望一个回调到一个承诺,你可以使用Promise.fromNode。按照Node.js世界的惯例,将使用参数err, result调用回调:

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); });
});