Возвращает результат лямбда-выражения .then () как результат функции - PullRequest
1 голос
/ 25 марта 2020

Я относительно новичок в js, поэтому, пожалуйста, прости меня, если моя формулировка не совсем верна. Я также создал jsfiddle , чтобы продемонстрировать проблему.

Обзор

В приложении, над которым я работаю, у меня есть функция с вызовом jquery ajax, например:

function scenario1(ajaxCfg) {
    return $.ajax(ajaxCfg)
}

Я хочу изменить эту функцию, но без изменения входов или выходов (так как эта функция вызывается сотни раз в моем приложение).

Изменение заключается в том, чтобы сделать другой вызов ajax, ПОТОМ сделать указанный вызов. В настоящее время у меня написано так:

function callDependency() { //example dependency
    return $.ajax(depUri)
}

function scenario2(ajaxCfg) {
    return callDependency().then(() => $.ajax(ajaxCfg))
}

Желаемый результат

Я хочу, чтобы эти два возвращаемых объекта были идентичны:

let result1 = scenario1(exampleCall)
let result2 = scenario2(exampleCall)

В частности, я хочу, чтобы result2 возвращал объект того же типа, что и result1.

Фактический результат

result1 является (очевидно) результатом вызов ajax, который является jqXHR объектом , который реализует интерфейс обещания и разрешается в то же значение, что и result2, что является стандартным обещанием.

, начиная с result2 не является jqXHR объектом, result2.error() не определено, в то время как result1.error() определено.

Я попытался смоделировать эти методы (просто добавив функцию .error к возвращаемому результату, для пример), но, к сожалению, даже при этом определяется result1.done().error, в то время как result2.done().error равно undefined.

Оборачивает (или разворачивает) его

В Короче говоря, я хочу вернуть jqXHR результат лямбда-функции .then() в scenario2 как результат функции scenario2. В псевдокоде я хочу:

function scenario2(ajaxCfg) {
    return callDependency().then(() => $.ajax(ajaxCfg)).unwrapThen()
} //return jqXHR

Ответы [ 3 ]

1 голос
/ 02 апреля 2020

Как насчет этого? Подход немного отличается, но в итоге вы можете связать .done() et c. к функции scenario2():

const exampleCall = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
const depUri = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};

function callDependency() { //example dependency
    return $.ajax(depUri).done(() => console.log('returned callDependancy'))
}

let obj = { //creating an object with the scenario2 as a method so that I can bind it with defer.promise()
    scenario2: function(ajaxCfg) {
        return $.ajax(ajaxCfg).done(() => console.log('returned senario2')) // Purposely NOT calling the exampleCall() function yet
    }
}

defer = $.Deferred(); // Using some JQuery magic to be able to return a jqXHR
defer.promise(obj); // Set the object as a promise
defer.resolve(callDependency()); // Invoking the callDependency() by default on promise resolve

obj.done(() => {
    obj.scenario2() // Resolving so the callDependency() function can be called
}).scenario2(exampleCall).done(() => { // Here you can invoke scenario2 and FINALLY chain whatever you want after everything has been called
    console.log('Here I can chain whatever I want with .done\(\) or .fail\(\) etc.')
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

Что мне нравится в этом способе, так это то, что вы можете просто продолжать добавлять методы к созданному вами объекту, а затем ко всем дополнительным функциям. которые построены поверх callDependency() могут быть в одном месте. Не только это, но вы можете использовать те же самые методы поверх других вызовов AJAX.

Подробнее об этом здесь.

Надеюсь, это поможет!

0 голосов
/ 03 апреля 2020

Я действительно думал о способе сделать это проще.

Вы можете сделать это, добавив метод к объекту-прототипу конструктора функции. Таким образом, любая созданная функция может наследовать этот метод, и вы все равно можете использовать синтаксис .done(). Он называется наследование прототипа :

const exampleCall = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};
const depUri = { url: 'https://code.jquery.com/jquery-1.12.4.min.js'};

function callDependency() {
    return $.ajax(depUri).done(() => console.log('returned callDependancy'))
}

Function.prototype.scenario2 = function(ajaxCfg, ...args) {
    return this(...args).then(() => $.ajax(ajaxCfg))
}

callDependency.scenario2(exampleCall).done(data => {
    console.log(data)
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
0 голосов
/ 01 апреля 2020

Я чувствую, что ваша жизнь стала бы намного проще, если бы вы использовали синтаксис async / await. Просто помните, что функции asyn c возвращают обещание. Таким образом, вы могли бы вместо этого написать:

async function scenario2(ajaxCfg) {
    let jqXhrResult;
    try {
        await callDependency();
        jqXhrResult = {
            jqXhr: $.ajax(ajaxCfg)
        };
    } catch() {
        // Error handling goes here
    }

    return jqXhrResult;
}
...