首先,这是一个非常具体的情况,故意以错误的方式将异步调用改造到非常同步的代码库中,该代码库有数千行之长,目前时间无法提供进行更改以“正确执行”的能力。它伤害了我身体的每一根纤维,但现实和理想往往不相符。我知道这很糟糕。
好了,我要怎么做才能:
function doSomething() {
var data;
function callBack(d) {
data = d;
}
myAsynchronousCall(param1, callBack);
// block here and return data when the callback is finished
return data;
}
示例(或缺少示例)都使用库和/或编译器,这两者都不适用于此解决方案。我需要一个具体的例子,如何使它块(例如不离开doSomething函数,直到回调被调用)而不冻结UI。如果这样的事情在JS中是可能的。
"不要告诉我我应该怎么做"正确的方式"之类的"
好的。但你真的应该用正确的方式去做……或者其他
“我需要一个具体的例子来说明如何让它成为块……不冻结用户界面。如果这样的事情在JS是可能的。”
不,如果不阻塞UI,就不可能阻塞正在运行的JavaScript。
由于缺乏信息,很难提供解决方案,但一种选择可能是让调用函数执行一些轮询来检查全局变量,然后让回调函数将数据设置为全局变量。
function doSomething() {
// callback sets the received data to a global var
function callBack(d) {
window.data = d;
}
// start the async
myAsynchronousCall(param1, callBack);
}
// start the function
doSomething();
// make sure the global is clear
window.data = null
// start polling at an interval until the data is found at the global
var intvl = setInterval(function() {
if (window.data) {
clearInterval(intvl);
console.log(data);
}
}, 100);
所有这些都假设您可以修改doSomething()。我不知道有没有可能。
如果它可以修改,那么我不知道为什么你不只是传递一个回调到doSomething()从另一个回调调用,但我最好在陷入麻烦之前停止。;)
哦,管他呢。你给出的例子表明它可以正确地完成,所以我将展示这个解决方案……
function doSomething( func ) {
function callBack(d) {
func( d );
}
myAsynchronousCall(param1, callBack);
}
doSomething(function(data) {
console.log(data);
});
因为您的示例包含一个传递给异步调用的回调,正确的方法是将一个函数传递给doSomething(),以便从回调调用。
当然,如果这是回调唯一做的事情,你只需要直接传递func…
myAsynchronousCall(param1, func);
看看JQuery的承诺:
http://api.jquery.com/promise/
http://api.jquery.com/jQuery.when/
http://api.jquery.com/deferred.promise/
重构代码:
var dfd = new jQuery.Deferred();
function callBack(data) {
dfd.notify(data);
}
// do the async call.
myAsynchronousCall(param1, callBack);
function doSomething(data) {
// do stuff with data...
}
$.when(dfd).then(doSomething);