Javascript Typescript-使用Frame.js的同步ajax调用(解决方案:jQueryFerred)
这个问题与typescript并不完全相关,但如果没有上下文,就不清楚我为什么会要求这样的行为。应该比较直截了当地理解你是否知道打字脚本 我有一个Typescript中的对话类实现,看起来像这样,只显示相关的方法和字段:Javascript Typescript-使用Frame.js的同步ajax调用(解决方案:jQueryFerred),javascript,typescript,framejs,Javascript,Typescript,Framejs,这个问题与typescript并不完全相关,但如果没有上下文,就不清楚我为什么会要求这样的行为。应该比较直截了当地理解你是否知道打字脚本 我有一个Typescript中的对话类实现,看起来像这样,只显示相关的方法和字段: class BaseDialog{ ... public dialogEl: JQuery; public AjaxLoadContent(route: string) { if (this.dialogEl !== unde
class BaseDialog{
...
public dialogEl: JQuery;
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined)
this.dialogEl.load(route);
return this;
}
public HtmlLoadContent(html: string) {
if (this.dialogEl !== undefined)
this.dialogEl.empty().html(html);
return this;
}
public Show() {
if (this.dialogEl !== undefined)
this.dialogEl.dialog("open");
}
...
}
我将从AjaxLoadContent和HtmlLoadContent返回此内容,以便我可以链接一个调用以显示以下内容:
var dialog = new BaseDialog();
dialog.AjaxLoadContent("/Account/Login").Show(); //Ajax call
dialog.HtmlLoadContent(someHtml).Show(); //Load from variable, no ajax call
我发现这种链接语法非常干净且合乎逻辑,因此我想继续使用它,但是,在ajax场景中,在ajax加载完成之前调用Show,这样对话框就会打开,然后在内容出现之前会有一个延迟。我无法提供要加载的回调,因为我想显式地将Show链接到调用上,而不是在内部调用它……因此,我需要某种同步机制
我现在正在研究Frame.js,以实现这种同步样式,而不必使用类似$.ajaxSetup{async:false;}的东西挂起浏览器。以下是我希望能奏效的答案:
但是,以下代码仍有延迟:
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined){
var that = this;
Frame(function (next) {
$.get(route, next);
});
Frame(function (next, response) {
that.dialogEl.html(response); //Breakpoint 1
});
Frame.init();
return this; //Breakpoint 2
}
}
然而,尽管我已经定义了显式的控制流,但这似乎不起作用,因为首先命中断点2。Show调用在返回this之后立即发生,因此加载一个空白对话框,然后最后从第二帧调用that.jQueryDialog.htmlresponse,在对话框已经显示之后加载内容,因此仍然存在延迟 如何实现这种同步行为?这正是我的目的。您可以将其用于所有这些,而无需在Frame.js上添加另一个依赖项。最简单的方法是从每个异步方法返回JQueryPromise,如下所示:
///<reference path="./jquery.d.ts">
class BaseDialog{
public dialogEl: JQuery;
public AjaxLoadContent(route: string):JQueryPromise {
var deferred = $.Deferred();
if (this.dialogEl !== undefined)
this.dialogEl.load(route)
.done(() => deferred.resolve())
.fail(() => deferred.reject());
return deferred.promise();
}
public HtmlLoadContent(html: string):void {
if (this.dialogEl !== undefined) {
this.dialogEl.empty().html(html);
}
public Show():void {
if (this.dialogEl !== undefined)
this.dialogEl.dialog("open");
}
}
var dialog = new BaseDialog();
dialog.AjaxLoadContent("something")
.done(() => dialog.Show());
这并不是一个干净的接口,但另一种方法是做一些非常聪明的编码,你的类将每个延迟的方法抛出到FIFO队列中,然后每个后续方法在队列中等待前一个延迟的方法,然后再开始执行。当然是可能的,如果您正在为大量外部消费设计此API,那么它可能值得一做。但是,如果你只是打算在一些内部项目中使用它,对我来说,这听起来像是太多的工作和维护。当然,这只是我的意见:-
您建议的接口的其他问题:1它没有任何处理错误的方法,这对jQueryFerred.fail处理程序来说是一个危险的问题;在调用类之间,它没有任何方式进行任何外部处理。如果您想在调用Show方法之前对内容进行转换,该怎么办?这正是我的目的。您可以将其用于所有这些,而无需在Frame.js上添加另一个依赖项。最简单的方法是从每个异步方法返回JQueryPromise,如下所示:
///<reference path="./jquery.d.ts">
class BaseDialog{
public dialogEl: JQuery;
public AjaxLoadContent(route: string):JQueryPromise {
var deferred = $.Deferred();
if (this.dialogEl !== undefined)
this.dialogEl.load(route)
.done(() => deferred.resolve())
.fail(() => deferred.reject());
return deferred.promise();
}
public HtmlLoadContent(html: string):void {
if (this.dialogEl !== undefined) {
this.dialogEl.empty().html(html);
}
public Show():void {
if (this.dialogEl !== undefined)
this.dialogEl.dialog("open");
}
}
var dialog = new BaseDialog();
dialog.AjaxLoadContent("something")
.done(() => dialog.Show());
这并不是一个干净的接口,但另一种方法是做一些非常聪明的编码,你的类将每个延迟的方法抛出到FIFO队列中,然后每个后续方法在队列中等待前一个延迟的方法,然后再开始执行。当然是可能的,如果您正在为大量外部消费设计此API,那么它可能值得一做。但是,如果你只是打算在一些内部项目中使用它,对我来说,这听起来像是太多的工作和维护。当然,这只是我的意见:-
您建议的接口的其他问题:1它没有任何处理错误的方法,这对jQueryFerred.fail处理程序来说是一个危险的问题;在调用类之间,它没有任何方式进行任何外部处理。如果您想在调用Show方法之前对内容进行转换,该怎么办?然而,尽管有显式的控制流,但这似乎不起作用,因为断点2首先被命中 实际上,流控件的工作方式与您编写的完全相同。只有框架函数中的内容才由框架控制。您不能在回调中使用return语句并期望它们返回调用函数 Ken的回答是正确的,使用jQuery Deferred将实现与上面示例中的Frame相同的目标。框架是为比您创建的序列长得多的序列而设计的。两者的行为方式相同,主要区别在于语法 老实说,我认为您所经历的延迟是进行AJAX调用所需的时间。也许我不理解你的问题,但框架部分看起来是正确的。以下是一些注意事项:
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined){
var that = this;
Frame(function (next) {
$.get(route, next); // great!
});
Frame(function (next, response) { // good use of passing variables!
that.dialogEl.html(response); // yep, will happen synchronously!
// return that; // unfortunately, this would only return 'that'
// to Frame, not to AjaxLoadContent.
// It's not possible to return the calling function
// from inside a callback.
next(); // the callback should be called here
// to complete the Frame sequence.
});
Frame.init();
return this; // notice that the return statement here is not in Frame?
}
}
然而,尽管有显式的控制流,但这似乎不起作用,因为首先命中断点2 实际上,流控件的工作方式与您编写的完全相同。只有框架函数中的内容才由框架控制。您不能在回调中使用return语句并期望它们返回调用函数 Ken的回答是正确的,使用jQuery 延迟将实现与上面示例中Frame相同的目标。框架是为比您创建的序列长得多的序列而设计的。两者的行为方式相同,主要区别在于语法 老实说,我认为您所经历的延迟是进行AJAX调用所需的时间。也许我不理解你的问题,但框架部分看起来是正确的。以下是一些注意事项:
public AjaxLoadContent(route: string) {
if (this.dialogEl !== undefined){
var that = this;
Frame(function (next) {
$.get(route, next); // great!
});
Frame(function (next, response) { // good use of passing variables!
that.dialogEl.html(response); // yep, will happen synchronously!
// return that; // unfortunately, this would only return 'that'
// to Frame, not to AjaxLoadContent.
// It's not possible to return the calling function
// from inside a callback.
next(); // the callback should be called here
// to complete the Frame sequence.
});
Frame.init();
return this; // notice that the return statement here is not in Frame?
}
}
谢谢你的回答+1也适用于失败处理程序和调用之间的外部处理的最后几点。这无疑使这个解决方案比我最初想要的更优越。刚刚有机会测试这个。从概念上讲,它非常有效。尽管我想指出记录加载没有.done或fail回调。您可以使用ajax{…}.done.fail或我使用success/error回调所做的操作来解析延迟:$.ajax{url:routeToLoad,success:htmlResponse:string=>{that.jQueryDialog.htmlhtmlhllResponse;deferred.resolve;},error:=>{deferred.reject;}};……无论如何,再次感谢。感谢您的出色回答。+1还感谢失败处理程序和调用之间的外部处理的最后几点。这无疑使此解决方案优于我最初想要的。刚刚有机会测试此解决方案。从概念上讲,效果很好。尽管我想指出的是,记录负载并不是这样拥有.done或fail回调。您可以使用ajax{…}.done.fail或我使用成功/错误回调所做的操作来解析延迟:$.ajax{url:routeToLoad,success:htmlResponse:string=>{that.jQueryDialog.htmlhtmlhlResponse;deferred.resolve;},错误:=>{deferred.reject;}};……无论如何,再次感谢。谢谢你的回答。我知道我在某种意义上误解了你的库不是为这个而设计的。不过,它看起来是一个很好的多功能插件,也许我以后会发现需要它。我会用它来加载模块,但Typescript在内部使用基于给定编译器的两个选项之一来处理flag:common.js或require.js。你应该指出Frame.js相对于require.js在向Typescript团队加载模块方面的优势,也许他们可以在未来的版本中选择使用它而不是require.js。此外,如果你愿意,你可以为Frame.js添加类型定义,或者甚至可以问Boris Yankov是否可以这样做。一切都很好。谢谢你的想法!我会研究一下。另外,说清楚一点,Frame完全能够完成你在这里所做的事情。它的工作原理与Deferred相同,而且我认为它的语法更可读。不是Frame不是为这个用途而设计的,而是Frame比Deferred更具可扩展性。再次感谢&祝你好运!usin如何g下一步,响应=>{},那么var=this;就不需要了谢谢你的回答。我知道我在某种意义上误解了你的库,它不是为这个而设计的。然而,它看起来是一个很好的多功能插件,也许我以后会发现需要它。我会用它来加载模块,但Typescript在内部使用基于给定c的两个选项之一来处理ompiler flag:common.js或require.js。您应该指出Frame.js在向Typescript团队加载模块方面优于require.js,也许他们可以在未来的版本中选择使用它而不是require.js。此外,如果您愿意,您可以为Frame.js添加类型定义,或者甚至可以询问Boris Yankov是否可以这样做。好吗最好的。谢谢你的想法!我会研究一下。另外,说得清楚,Frame完全能够完成你在这里所做的事情。它的工作原理与Deferred相同,而且我认为它的语法可读性更高。不是Frame不是为这个用途而设计的,而是Frame比Deferred更具可伸缩性。再次感谢&祝你好运!多么好啊使用next,response=>{},则不需要=this;的变量