Javascript 然后在jQuery中始终保持干燥

Javascript 然后在jQuery中始终保持干燥,javascript,jquery,promise,Javascript,Jquery,Promise,我有以下示例JS代码: function loadData(url, data) { return $.get(url, data ? data : {}); } function example1() { showSpinner(); $.when(loadData('/example1', { hello: 'world' })) .then(function (resp) { // do something with t

我有以下示例JS代码:

function loadData(url, data) {
    return $.get(url, data ? data : {});
}

function example1() {

    showSpinner();

    $.when(loadData('/example1', { hello: 'world' }))
        .then(function (resp) {
            // do something with the data
        })
        .always(function(){
            hideSpinner();
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            handleError(jqXHR);
        });
}

function example2() {

    showSpinner();

    $.when(loadData('/example2', { hello: 'world' }))
        .then(function (resp) {
            // do something with the data
        })
        .then(function () {
            // do something else
        })
        .always(function(){
            hideSpinner();
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            handleError(jqXHR);
        });
}
example1()
example2()
使用相同的承诺逻辑,对返回的数据执行不同的操作,然后始终隐藏微调器,并以相同的方式处理故障(如果有)。问题是,在每个示例中加载数据并有多个
之后,我可能想做不同的事情

但是,我必须重复
始终
失败
代码。如何使它们更干燥,这样它们只编写一次,但在两种场景中都使用(如果需要,还可以使用其他示例)。因此,我不能将when移到一个方法中并传递回调,因为可能存在多个不同的then's所以这不起作用:

function customPromise(load, callback) {

    showSpinner();

    $.when(load)
    .then(function (resp) {
        callback(resp);
    })
    .always(function(){
        hideSpinner();
    })
    .fail(function (jqXHR, textStatus, errorThrown) {
        handleError(jqXHR);
    });

}

function example3() {
    customPromise(loadData('/example2', { hello: 'world' }));
}
也许您可以将
.when()
分解为一个返回承诺本身的函数,然后调用该函数并使用
.then()
链接到返回的承诺上,例如foobar().then().then()。没有法律规定,
总是
失败
必须排在链的最后

这是一个解决方案的草图,我还没有测试过

function loadData(url, data) {
    return $.get(url, data ? data : {});
}

function wrapWhen(endpoint, data) {

    // return a promise
    return $.when(loadData(endpoint, data))
        .always(function(){
            hideSpinner();
        })
        .fail(function (jqXHR, textStatus, errorThrown) {
            handleError(jqXHR);
        });
}

function example1() {

    showSpinner();

    wrapWhen('/example1', {hello: 'world'})
        .then(function (resp) {
            // do something with the data
        });
}

function example2() {

    showSpinner();

    wrapWhen('/example2', {hello: 'world'})
        .then(function (resp) {
            // do something with the data
        })
        .then(function () {
            // do something else
        });
}

如果您有连续且未知数量的回调,我建议您将整个处理移到创建的函数:

function handleRequest(url, data, errorCallback) {
    // create promise
    let promise = $.get(url, data ? data : {});

    // if callback functions provided as args, chain them in `then()` calls
    if (arguments.length > 3) {
        let callbacks = Array.slice.call(arguments, 3);
        let fn = (results) => (results);
        let callback;
        for (let i = 0; i < callbacks.length; i++) {
            callback = callbacks[i] instanceof Function ? callbacks[i] : fn;
            promise.then(callback);
        }
    }

    // handle static behavior
    promise.always(() => {
        hideSpinner();
    })
    .fail(errorCallback);

    // return the created promise
    return promise;
}

我能想到这样的事情。不确定是否应由
loadData
负责显示微调器

$(函数(){
例1();
例2();
});
函数loadData(url、数据){
showSpinner();
返回$.get(url,数据?数据:{})
.always(函数(){
hideSpinner();
})
.fail(函数(jqXHR、textStatus、errorshown){
handleError(jqXHR);
});
}
函数示例1(){
$.when(加载数据('https://jsonplaceholder.typicode.com/users', {
你好:'世界'
}))
.然后(功能(resp){
console.log(分别为长度+接收到的长度数据);
});
}
函数示例2(){
$.when(加载数据('https://jsonplaceholder.typicode.com/posts', {
你好:'世界'
}))
.然后(功能(resp){
返回响应;
})
.then(功能(数据){
console.log(data.length+‘接收到的长度数据’);
});
}
函数showSpinner(){
log('显示微调器…');
}
函数hideSpinner(){
log('隐藏微调器…');
}
函数句柄错误(xhr){
控制台错误(xhr);
}

我还没有完全考虑过这一点,但也许你可以在
时将
分解成一个返回承诺本身的函数,然后调用该函数并链接到返回的承诺上,比如
foobar().then().then()
。没有法律规定,
fail
必须排在最后。
example1
example2
是否相互排斥?当两者同时执行时会发生什么;较早完成的那个隐藏了旋转器?我不明白。为什么您提议的
customPromise
功能不起作用?这正是正确的方法。您是否遗漏了
参数作为
handleRequest
中的参数?
参数是每个JS函数中的给定变量。你可以了解它。Cool从来都不知道像这样的
参数。啊,哇,我没有意识到“总是”和“失败”可以像这样移动。@Cameron——正如我在评论中强调的那样,如果同时执行
example1
example2
,但其中一个提前完成并隐藏微调器,则会出现问题。
handleRequest(
    '/example',
    {},
    (jqXHR, textStatus, errorThrown) => {
        handleError(jqXHR);
    },
    (resp) => {
        // do something with the data
    },
    () => {
        // do something else
    }
);