你能判断 object 是否在等待 TypeScript 中的异步成员函数吗?
Can you tell if an object is awaiting an async member function in TypeScript?
我正在使用 TypeScript 开发 client-side 网络应用程序。
我有自己的“框架”,我开发了一个 class (ViewBinder),它使用异步“显示”方法从服务器加载信息,提取 HTML,然后插入它进入 parent “占位符”元素内的文档。然后,其派生的 classes 可以将来自客户端状态 object 的数据“绑定”到加载的 HTML.
这里是 class 中的一些代码供参考(不是可执行示例):
export class ViewBinder extends PropertyChangedNotifier {
// Lots of member stuff not shown for brevity...
public async show(callbackAfterShow?: (wasSuccessful: boolean) => void): Promise<HtmlLoadViewResult> {
this.showWasCanceled = false;
const loadResult = await this.loadView();
if (this.showWasCanceled) { // Helps my situation some but not fully
// If this.clear() was called during loadView, we just move on...
loadResult.wasCanceled = true;
} else {
// HERE is where I can have a problem: if this.clear() is called
// while a derived class is doing its setupAfterShowing, the underlying
// HTML will be removed and the attempt to setup (binding data to the
// HTML) will cause an unwanted error.
await this.setupAfterShowing(loadResult);
// CODE REMOVED FOR BREVITY
}
return loadResult;
}
public clear(): void {
// If the show function is awaiting anything, tell it it was canceled
// BUT: what I WANT to do is somehow wait until show() is done before
// continuing the execution of this function... see the question text
this.showWasCanceled = true;
this.localViewBinders.forEach((viewBinder) => viewBinder?.clear());
this.localBindingContexts.forEach((context) => context?.clear());
if (this.parentElement) {
this.parentElement.innerHTML = "";
if (this.isModalDialog) {
this.parentElement.remove();
} else {
this.collapse();
}
this.parentElement = null; // We are no longer associated with the element
this.notifyPropertyChanged("visibility");
this.removeAllPropertyChangedListeners();
}
}
}
请注意,派生的 classes 将开发 setupAfterShowing
方法,将来自客户端状态 object 的数据“绑定”到已加载的 HTML(并且可以调用 show
自己的“child”ViewBinders)。还有一个 clear
命令从 parent 元素中删除所有 HTML 并清除所有“数据绑定”。
但是,在 ViewBinder 等待 show
命令时(在 loadView
或 setupAfterShowing
调用期间,底层客户端状态 object 发生变化的情况很少见,并且这些更改导致代码调用 clear
方法,删除应该插入 HTML 的 parent 元素的主体并绑定数据。
一般来说,如果 ViewBinder 找不到 parent 元素或无法在该元素中找到显示数据的位置,我认为这是一个错误并抛出错误。但是,在这种情况下,HTML 将在异步代码等待结果时“合法地”删除。
请注意,我已尝试使用 showWasCanceled
来避免此问题,但派生的 setupAfterShowing
方法中存在太多潜在问题,以确保我始终在 showWasCanceled
设置为 true
.
所以,这是我的问题:
我的 clear
函数是否有办法确定 show
函数是否“正在等待”并暂停执行直到“显示”完成?
这样做的一种方法是创建一些字段来保存此类信息,例如
private promise;
private resolve;
private reject;
init() {
this.promise = new Promise((res, rej)=>{
this.resolve = res;
this.reject= rej;
});
}
public async show(...) {
...
resolve(null); // or reject if any error thrown above
}
public async clear() {
await this.promise;
...
}
我将接受@ABOS 的回答,因为它本着 async/await 流程的精神提供了一个解决方案(让 clear()
等待 show()
可以解决的承诺).
但是,我最终采取了某种 old-school 的方法,并想在此处记录下来以防其他人发现它有用。
请注意,这也使我不必制作 clear
一个 async
方法(这导致我在很多地方去 async
“all-the-way-down” ).
描述如下:
首先,我向 class 添加了两个布尔值:clearWasCalled
和 isRunningShow
。
调用show()
时,它设置this.clearWasCalled = false
和this.isRunningShow = true
。在 show()
的末尾,它设置 this.isRunningShow = false
,如果 this.clearWasCalled === true
,它将调用 this.clear()
。
当clear()
被调用时,它检查是否this.isRunningShow === true
,如果是,它设置this.clearWasCalled = true
并退出。
因此,在等待 show()
方法时,如果调用 clear()
,它不会中断 show()
函数,而只是设置一个标志。 show()
完成后,它会检查标志是否已设置,如果已设置,它会确保 clear
操作已完成。
这里是代码中的基本思想:
export class ViewBinder extends PropertyChangedNotifier {
// Lots of member stuff not shown for brevity...
public clearWasCalled = false;
public isRunningShow = false;
public async show(callbackAfterShow?: (wasSuccessful: boolean) => void): Promise<HtmlLoadViewResult> {
this.clearWasCalled = false;
this.isRunningShow = true;
const loadResult = await this.loadView();
if (this.clearWasCalled === false) { // Just in case...
// If this.clear() was called during loadView, we just move on...
loadResult.wasCanceled = true;
} else {
await this.setupAfterShowing(loadResult);
// CODE REMOVED FOR BREVITY
}
this.isRunningShow = false;
if (this.clearWasCalled) {
this.clear();
loadResult.wasCanceled = true;
}
return loadResult;
}
public clear(): void {
// If we're running a show method, don't clear until it's done
if (this.isRunningShow) {
this.clearWasCalled = true;
return;
}
// PERFORM CLEAR ACTIONS...
}
}
我正在使用 TypeScript 开发 client-side 网络应用程序。
我有自己的“框架”,我开发了一个 class (ViewBinder),它使用异步“显示”方法从服务器加载信息,提取 HTML,然后插入它进入 parent “占位符”元素内的文档。然后,其派生的 classes 可以将来自客户端状态 object 的数据“绑定”到加载的 HTML.
这里是 class 中的一些代码供参考(不是可执行示例):
export class ViewBinder extends PropertyChangedNotifier {
// Lots of member stuff not shown for brevity...
public async show(callbackAfterShow?: (wasSuccessful: boolean) => void): Promise<HtmlLoadViewResult> {
this.showWasCanceled = false;
const loadResult = await this.loadView();
if (this.showWasCanceled) { // Helps my situation some but not fully
// If this.clear() was called during loadView, we just move on...
loadResult.wasCanceled = true;
} else {
// HERE is where I can have a problem: if this.clear() is called
// while a derived class is doing its setupAfterShowing, the underlying
// HTML will be removed and the attempt to setup (binding data to the
// HTML) will cause an unwanted error.
await this.setupAfterShowing(loadResult);
// CODE REMOVED FOR BREVITY
}
return loadResult;
}
public clear(): void {
// If the show function is awaiting anything, tell it it was canceled
// BUT: what I WANT to do is somehow wait until show() is done before
// continuing the execution of this function... see the question text
this.showWasCanceled = true;
this.localViewBinders.forEach((viewBinder) => viewBinder?.clear());
this.localBindingContexts.forEach((context) => context?.clear());
if (this.parentElement) {
this.parentElement.innerHTML = "";
if (this.isModalDialog) {
this.parentElement.remove();
} else {
this.collapse();
}
this.parentElement = null; // We are no longer associated with the element
this.notifyPropertyChanged("visibility");
this.removeAllPropertyChangedListeners();
}
}
}
请注意,派生的 classes 将开发 setupAfterShowing
方法,将来自客户端状态 object 的数据“绑定”到已加载的 HTML(并且可以调用 show
自己的“child”ViewBinders)。还有一个 clear
命令从 parent 元素中删除所有 HTML 并清除所有“数据绑定”。
但是,在 ViewBinder 等待 show
命令时(在 loadView
或 setupAfterShowing
调用期间,底层客户端状态 object 发生变化的情况很少见,并且这些更改导致代码调用 clear
方法,删除应该插入 HTML 的 parent 元素的主体并绑定数据。
一般来说,如果 ViewBinder 找不到 parent 元素或无法在该元素中找到显示数据的位置,我认为这是一个错误并抛出错误。但是,在这种情况下,HTML 将在异步代码等待结果时“合法地”删除。
请注意,我已尝试使用 showWasCanceled
来避免此问题,但派生的 setupAfterShowing
方法中存在太多潜在问题,以确保我始终在 showWasCanceled
设置为 true
.
所以,这是我的问题:
我的 clear
函数是否有办法确定 show
函数是否“正在等待”并暂停执行直到“显示”完成?
这样做的一种方法是创建一些字段来保存此类信息,例如
private promise;
private resolve;
private reject;
init() {
this.promise = new Promise((res, rej)=>{
this.resolve = res;
this.reject= rej;
});
}
public async show(...) {
...
resolve(null); // or reject if any error thrown above
}
public async clear() {
await this.promise;
...
}
我将接受@ABOS 的回答,因为它本着 async/await 流程的精神提供了一个解决方案(让 clear()
等待 show()
可以解决的承诺).
但是,我最终采取了某种 old-school 的方法,并想在此处记录下来以防其他人发现它有用。
请注意,这也使我不必制作 clear
一个 async
方法(这导致我在很多地方去 async
“all-the-way-down” ).
描述如下:
首先,我向 class 添加了两个布尔值:clearWasCalled
和 isRunningShow
。
调用show()
时,它设置this.clearWasCalled = false
和this.isRunningShow = true
。在 show()
的末尾,它设置 this.isRunningShow = false
,如果 this.clearWasCalled === true
,它将调用 this.clear()
。
当clear()
被调用时,它检查是否this.isRunningShow === true
,如果是,它设置this.clearWasCalled = true
并退出。
因此,在等待 show()
方法时,如果调用 clear()
,它不会中断 show()
函数,而只是设置一个标志。 show()
完成后,它会检查标志是否已设置,如果已设置,它会确保 clear
操作已完成。
这里是代码中的基本思想:
export class ViewBinder extends PropertyChangedNotifier {
// Lots of member stuff not shown for brevity...
public clearWasCalled = false;
public isRunningShow = false;
public async show(callbackAfterShow?: (wasSuccessful: boolean) => void): Promise<HtmlLoadViewResult> {
this.clearWasCalled = false;
this.isRunningShow = true;
const loadResult = await this.loadView();
if (this.clearWasCalled === false) { // Just in case...
// If this.clear() was called during loadView, we just move on...
loadResult.wasCanceled = true;
} else {
await this.setupAfterShowing(loadResult);
// CODE REMOVED FOR BREVITY
}
this.isRunningShow = false;
if (this.clearWasCalled) {
this.clear();
loadResult.wasCanceled = true;
}
return loadResult;
}
public clear(): void {
// If we're running a show method, don't clear until it's done
if (this.isRunningShow) {
this.clearWasCalled = true;
return;
}
// PERFORM CLEAR ACTIONS...
}
}