我如何同步从不同来源调用的回调(从回调中)?
How can i synchronize callbacks (from within the callback) called from different sources?
我的 ui-框架 (openui5) 在同步两个不同的回调时遇到问题。一个是来自渲染完成的 ui 事件的回调,另一个是来自数据访问(ajax 调用)的异步回调,由使用的模型 class 完成. ui-事件回调需要来自数据回调的数据。
为了简化这里的简化代码片段以演示问题。我想要,onRouteMatched-Code 应该在 onUpdateFinished 完成时执行代码。在此示例中,我使用我的 asyncInit-Method 创建了异步场景。这只是为了创建一个简单的测试场景。实际上,这个 onUpdateFinished 由我的数据模型 class 调用,onRouteMatched 由另一个框架 - class 事件调用。
let testClass = {
myUser : "",
// Method definition:
asyncInit : function() {
me = this;
let timer1 = Math.round(Math.random()*10000);
let timer2 = Math.round(Math.random()*10000);
setTimeout(function(){ me.onUpdateFinished();} , timer1);
setTimeout(function(){ me.onRouteMatched();} , timer2);
},
onUpdateFinished : function(oEvent) {
console.warn("onUpdateFinished.....setting Data")
this.myUser = 'doe';
},
onRouteMatched : function(oEvent) {
// Event though this callback is
// called before onUpddate
console.warn("onRouteMatched...., myData="+this.myUser);
}
}
testClass.asyncInit();
在此示例中,onUpdateFinished 和 onRouteMatched 由 setTimeout 调用,超时值为 0-9 秒。
如果先调用 onUpdateFinished,则一切正常并且 onRouteMatched 中的用户是 "doe"。
如果在 onUpdateFinished 之前调用 onRouteMatched 则用户是 "undefined".
一个不太干净的解决方法是使用 "sync" 变量并在 onRouteMatched 中检查它(参见示例)。
我还想到了 promise、async 和 await 之类的东西。但正如我所见,在所有示例中,我必须能够控制在我的代码中启动回调。但在这种情况下,我对回调的调用者没有影响。
这里是我的例子 "workaround"
let testClass = {
myUser : "",
updOk : false,
// Method definition:
asyncInit : function() {
me = this;
let timer1 = Math.round(Math.random()*10000);
let timer2 = Math.round(Math.random()*10000);
setTimeout(function(){ me.onUpdateFinished();} , timer1);
setTimeout(function(){ me.onRouteMatched();} , timer2);
},
onUpdateFinished : function(oEvent) {
console.warn("onUpdateFinished.....setting Data")
this.myUser = 'doe';
this.updOk = true;
},
onRouteMatched : function(oEvent) {
// Event though this callback is
// called before onUpddate
me = this;
if (!this.updOk) {
console.log("onRouteMatched called...");
setTimeout(function(){
console.warn("Update still not finished");
me.onRouteMatched();
},1000)
return;
}
console.warn("onRouteMatched...., myData="+this.myUser);
}
}
testClass.asyncInit();
围绕用户建立承诺:
let userArrived, user = new Promise(resolve => userArrived = resolve);
然后,在 onUpdateFinished
中解决承诺:
onUpdateFinished : function(oEvent) {
userArrived("John Doe");
}
里面onRouteMatched
消费承诺:
onRouteMatched : function(oEvent) {
user.then(username => {
console.log(`${username} is ready!`);
});
}
或者使用 async
/ await
甚至可以写成:
async onRouteMatched(oEvent) {
const username = await user;
console.log(`${username} is ready!`);
},
我的 ui-框架 (openui5) 在同步两个不同的回调时遇到问题。一个是来自渲染完成的 ui 事件的回调,另一个是来自数据访问(ajax 调用)的异步回调,由使用的模型 class 完成. ui-事件回调需要来自数据回调的数据。
为了简化这里的简化代码片段以演示问题。我想要,onRouteMatched-Code 应该在 onUpdateFinished 完成时执行代码。在此示例中,我使用我的 asyncInit-Method 创建了异步场景。这只是为了创建一个简单的测试场景。实际上,这个 onUpdateFinished 由我的数据模型 class 调用,onRouteMatched 由另一个框架 - class 事件调用。
let testClass = {
myUser : "",
// Method definition:
asyncInit : function() {
me = this;
let timer1 = Math.round(Math.random()*10000);
let timer2 = Math.round(Math.random()*10000);
setTimeout(function(){ me.onUpdateFinished();} , timer1);
setTimeout(function(){ me.onRouteMatched();} , timer2);
},
onUpdateFinished : function(oEvent) {
console.warn("onUpdateFinished.....setting Data")
this.myUser = 'doe';
},
onRouteMatched : function(oEvent) {
// Event though this callback is
// called before onUpddate
console.warn("onRouteMatched...., myData="+this.myUser);
}
}
testClass.asyncInit();
在此示例中,onUpdateFinished 和 onRouteMatched 由 setTimeout 调用,超时值为 0-9 秒。 如果先调用 onUpdateFinished,则一切正常并且 onRouteMatched 中的用户是 "doe"。 如果在 onUpdateFinished 之前调用 onRouteMatched 则用户是 "undefined".
一个不太干净的解决方法是使用 "sync" 变量并在 onRouteMatched 中检查它(参见示例)。 我还想到了 promise、async 和 await 之类的东西。但正如我所见,在所有示例中,我必须能够控制在我的代码中启动回调。但在这种情况下,我对回调的调用者没有影响。
这里是我的例子 "workaround"
let testClass = {
myUser : "",
updOk : false,
// Method definition:
asyncInit : function() {
me = this;
let timer1 = Math.round(Math.random()*10000);
let timer2 = Math.round(Math.random()*10000);
setTimeout(function(){ me.onUpdateFinished();} , timer1);
setTimeout(function(){ me.onRouteMatched();} , timer2);
},
onUpdateFinished : function(oEvent) {
console.warn("onUpdateFinished.....setting Data")
this.myUser = 'doe';
this.updOk = true;
},
onRouteMatched : function(oEvent) {
// Event though this callback is
// called before onUpddate
me = this;
if (!this.updOk) {
console.log("onRouteMatched called...");
setTimeout(function(){
console.warn("Update still not finished");
me.onRouteMatched();
},1000)
return;
}
console.warn("onRouteMatched...., myData="+this.myUser);
}
}
testClass.asyncInit();
围绕用户建立承诺:
let userArrived, user = new Promise(resolve => userArrived = resolve);
然后,在 onUpdateFinished
中解决承诺:
onUpdateFinished : function(oEvent) {
userArrived("John Doe");
}
里面onRouteMatched
消费承诺:
onRouteMatched : function(oEvent) {
user.then(username => {
console.log(`${username} is ready!`);
});
}
或者使用 async
/ await
甚至可以写成:
async onRouteMatched(oEvent) {
const username = await user;
console.log(`${username} is ready!`);
},