填充某些属性的javascript异步调用

Posted

技术标签:

【中文标题】填充某些属性的javascript异步调用【英文标题】:javascript asynchronous calls that populate some property 【发布时间】:2012-01-03 13:53:00 【问题描述】:

我有一个 javascript 对象,其中包含一些图像字符串作为其属性。实例化此对象后,会立即进行 AJAX 调用以填充此属性。

同时,我的视图函数尝试读取新实例化的实例并尝试显示该对象。正如预期的那样,AJAX 调用可能还没有完成,所以它将无法读取正确的图像 url。

此问题的一个解决方案是通过 AJAX 调用传入一些回调函数,该函数在完成时修改图像的来源,但这会引入对模型和视图的大量依赖,我试图保持我的 MVC 尽可能独立,所以我的视图函数现在只是将该对象作为参数,读取所有属性并显示它。

使 AJAX 同步不是一种选择,因为我有很多这样的对象正在初始化,并且一次只会显示一个,因此使所有 AJAX 调用同步将是一个代价太高的权衡。

有什么好的方法可以解决这个问题?视图函数的形式是:

function displayObj(object) 
    var prop1 = object.getProp1();
    // this could be the image file that depends on AJAX result
    var prop2 = object.getProp2(); 

理想情况下,我想将此任务委托给 getter,这样视图函数就不必担心对象的间隔状态。 getter 可以通过检查图像是否存在来处理这个问题,如果没有,则等待,然后仅在实际图像字符串存在时才返回。但是,阻塞等待肯定会阻塞 AJAX 进程,所以它是一个死锁,而非阻塞等待会让 getter 返回,视图函数将获取 null 数据。

请阐明这种情况或建议我可以组织代码的其他方法。非常感谢!

【问题讨论】:

I have an javascript object that includes some image strings as its parameter。这在技术上是错误的,因为对象无法获得参数。对象具有属性,也称为属性 是的,这就是我的意思,属性,而不是参数。 这个问题的答案很大程度上取决于您使用的是哪个 AJAX 框架(或者您是否只是直接调用 XHR)。例如,如果您使用具有承诺的功能,那么将显示更新添加到 then() 处理程序将是答案。您能否进一步说明您正在使用什么? @chuckj 我正在使用 jQuery,它确实提供了一个很好的回调机制,但正如我所提到的,我希望有一种方法可以做到这一点,它不会引入对模型和视图的依赖。我试图让控制器成为这里唯一的中间人。 【参考方案1】:

我会对 MVC 角色不那么严格,让模型对象返回 DOM <img> 对象。

// model object starts loading upon instantiation
var loader = new Loader();

// however the img tag is available immediately.
// the loader will update the src when ajax
// calls complete.
document.body.appendChild(loader.getImg());

【讨论】:

谢谢,马丁。我觉得我在这里相当于你的加载器对象实际上只是模型,即图像 url 字符串。它根本不关心 DOM。视图函数正在动态生成 img 对象,这正是读取源代码的时间,但可能不可用。 是的,这就是我提出“不那么严格的 MVC”的原因。我发现很多时候,如果你牺牲一点严格性,在 javascript 中你会得到更简洁的代码。 感谢您的建议。我不只是为了严格而严格。我只是觉得拥有 mutual 依赖项是一个非常糟糕的主意。但正如我所提到的,我最终决定只使用一个完整的同步模型。无论如何,谢谢。【参考方案2】:

由于您的 cmets 使用的是 jQuery,我建议您调用从 ajax() 方法返回的请求的 done() 方法。例如,

var request = $.ajax("example.php");
request.done(notifyWhenSuccess);
request.fail(notifyWhenFailed);

jQuery 返回的这个请求是来自 CommonJS 的 Promise 模式的超集。此外,仅仅因为它在 jQuery 中,不要考虑视图的 ajax 调用部分,而是将其视为模型的一部分。使用done() 方法更新模型,然后通过数据更改事件通知视图。

【讨论】:

谢谢,@chuckj。这确实是我开始实施的,但过了一会儿就变得混乱了。 ajax 调用已经只是模型的一部分,所以notifyWhenSuccess 将是一个视图函数,例如view.updateImg。但我不能保证视图函数已经初始化并创建了 DOM 对象(因为 DOM 对象是动态创建的,因此依赖于模型)。最后,应用程序的其他部分基本上迫使我使用同步模型,这就是我现在所拥有的。 我会牺牲 MVC 的纯度来让我的 ajax 调用异步。同步 ajax 调用会扼杀响应性,并可能导致用户认为页面已挂起。

以上是关于填充某些属性的javascript异步调用的主要内容,如果未能解决你的问题,请参考以下文章

从 Firestore 异步调用填充 RecyclerView

如何在异步调用期间填充数组并将其发送到响应对象中

在 C# 中的类构造函数中调用异步方法 [重复]

有没有办法在异步函数中等待多个等待调用?

如何实现 javascript “同步”调用 app 代码

ExtJs 处理异步调用