Javascript 将.then()lambda表达式的结果作为函数结果返回
我对js比较陌生,所以如果我的措辞不太正确,请原谅我。我还创建了一个示例来演示这个问题 概述 在我正在开发的应用程序中,我有一个带有jquery ajax调用的函数,如下所示:Javascript 将.then()lambda表达式的结果作为函数结果返回,javascript,jquery,ajax,promise,jqxhr,Javascript,Jquery,Ajax,Promise,Jqxhr,我对js比较陌生,所以如果我的措辞不太正确,请原谅我。我还创建了一个示例来演示这个问题 概述 在我正在开发的应用程序中,我有一个带有jquery ajax调用的函数,如下所示: function scenario1(ajaxCfg) { return $.ajax(ajaxCfg) } function callDependency() { //example dependency return $.ajax(depUri) } function scenario2(ajax
function scenario1(ajaxCfg) {
return $.ajax(ajaxCfg)
}
function callDependency() { //example dependency
return $.ajax(depUri)
}
function scenario2(ajaxCfg) {
return callDependency().then(() => $.ajax(ajaxCfg))
}
我想更改此函数,但不以任何方式更改输入或输出(因为此函数在我的应用程序中被调用数百次)
更改是进行不同的ajax调用,然后进行指定的调用。我现在写的是这样的:
function scenario1(ajaxCfg) {
return $.ajax(ajaxCfg)
}
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调用的结果,它是一个实现promise接口的jqXHR
,并解析为与标准promise的result2
相同的值
由于result2
不是jqXHR
对象,result2.error()
未定义,而result1.error()已定义
我确实尝试模拟这些方法(例如,简单地向返回结果添加一个.error
函数),但不幸的是,即使这样做,result1.done().error
是在result2.done()时定义的。error
是未定义的
将其包装(或展开)
简而言之,我想返回scenario2
中jqXHR
函数的result.then()
lambda函数作为scenario2
函数的结果。在伪代码中,我希望:
function scenario2(ajaxCfg) {
return callDependency().then(() => $.ajax(ajaxCfg)).unwrapThen()
} //return jqXHR
我觉得如果使用async/await语法,您的生活会轻松得多。请记住,异步函数会返回一个承诺。所以你可以写:
async function scenario2(ajaxCfg) {
let jqXhrResult;
try {
await callDependency();
jqXhrResult = {
jqXhr: $.ajax(ajaxCfg)
};
} catch() {
// Error handling goes here
}
return jqXhrResult;
}
像这样的怎么样?方法稍有不同,但最终您可以将.done()
等链接到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'};
函数callDependency(){//示例依赖项
return$.ajax(depUri).done(()=>console.log('returned callDependancy'))
}
让obj={//创建一个使用scenario2作为方法的对象,这样我就可以用defer.promise()绑定它
场景2:功能(ajaxCfg){
return$.ajax(ajaxCfg).done(()=>console.log('returned senario2'))//故意不调用exampleCall()函数
}
}
延迟=$.Deferred();//使用一些JQuery魔术来返回jqXHR
延迟承诺(obj);//将目标设定为承诺
defer.resolve(callDependency());//默认情况下在promise resolve上调用callDependency()
目标完成(()=>{
obj.scenario2()//解析以便调用callDependency()函数
}).scenario2(exampleCall).done(()=>{//在这里,您可以调用scenario2,并在调用所有内容后最终链接您想要的任何内容
console.log('在这里我可以用.done\(\)或.fail\(\)等链接我想要的任何东西。')
})
我实际上想到了一种更简单的方法
您可以通过向函数构造函数的原型对象添加方法来实现。这样,任何创建的函数都可以继承该方法,并且仍然可以使用.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'};
函数callDependency(){
return$.ajax(depUri).done(()=>console.log('returned callDependancy'))
}
Function.prototype.scenario2=函数(ajaxCfg,…args){
返回此(…args)。然后(()=>$.ajax(ajaxCfg))
}
callDependency.scenario2(exampleCall).done(数据=>{
console.log(数据)
})
^^^^^ senario1在ajax调用之前没有返回,更迂腐一些:$.ajax()
返回一个“jqXHR对象”,它不是一个承诺
,而是一个实现承诺
接口的对象。@Andreas oops!修正了。JSFIDLE是正确的,我只是抄错了。但还有一点:就是这样,我想要jgXHR对象。如何将其作为函数的返回值?一个jqXHR
对象没有.resolve()
和.reject()
方法,因此它不是一个延迟对象。这实际上是一个(jQuery)承诺。您能具体说明您的主要目标是什么吗?您希望在这里实现什么?不幸的是,异步函数的结果不是jqXHR对象,因此它不支持相同的方法(例如.done().error()
)。我已经更新了我的答案,以适应错误处理。在等待场景2函数之后,您可以将错误回调中的逻辑移到catch块中,并将完成回调的逻辑移到catch块中。关于jquery jqXHR/promise对象是如何解析的,这里有一个非常好的解释:我已经将您的建议添加到JSFIDLE中;我希望这能说明为什么这不是一个解决办法。如果我遗漏了什么,请告诉我。我再次更新了答案,并在此处进行了测试:。作为一个简短的提示,我真的不鼓励这样做,即使这样做是有效的。最好的方法是重构前端,使其符合asyc/WAIT语法,但我知道您可能会被迫不这样做,因为您提到此功能在您的应用程序中随处可见;您已将调用程序更改为在异步函数中运行,async function runLogic()
。正如您所想象的,我不能修改应用程序中的每个调用程序,使其在异步函数中运行。但是,是的,我同意这不是一个构建新应用程序的好模式。我无法在