如何检查对象实例属性Promise[]是否包含特定的Promise?

问题描述 投票:0回答:1

我开发了 React 应用程序并使用一些全局可用的对象实例来处理组件逻辑中的重复任务。实现很简单:

class SomeService {
    // Some service logic
}

const someService = new SomeService();

export default someService;

然后我使用

import
导入 React 功能组件中的实例,并在这些对象上调用正确的方法。这样我实现了负责从远程获取数据的
APIService

class APIService {
    async get<Entity extends IEntity>(
        url: string,
        data: IQueryParams<Entity>,
        onSuccess?: (response: IResponse) => void,
        onError?: (error: IResponseDetails) => void,
        onNotFound?: (error: IResponseDetails) => void
    ): Promise<boolean> {
        // Some logic
    }

    // Other methods...
}

因此,每当我想在组件中执行 GET 请求时,我都可以使用:

APIService.get(url, data, (response: IResponse) => {
    // Success
), (error: IResponseDetails) => {
    // Error
});

最近,我决定在

AbortController
类中实现
APIService
功能,以便在组件卸载时中止
fetch
请求。我想通过以下方式实现它:

useEffect(() => {
    const request = APIService.get(url, data, (response: IResponse) => {
        // Success
    ), (error: IResponseDetails) => {
        // Error
    });

    return () => {
        APIService.abort(request);
    }
}, []);

在底层,

APIService
类包含
private queue: Promise<boolean>[]
属性,用于跟踪在
fetch
调用期间附加到它的所有未决承诺,并在承诺解决时将其删除。

APIService.abort
方法应该以
Promise<boolean>
为参数,在
queue: Promise<boolean>[]
数组中找到promise并触发
AbortSignal

我遇到的问题是,如果传递的承诺包含在

APIService.abort
数组中,我无法检查
queue
方法(我使用
get
将其添加到
this.queue.push(promise)
方法中)。我知道
Promise
是一个对象,并通过引用传递,但无论我尝试使用
queue
(始终返回
this.queue.indexOf(promise)
)在
-1
数组中找到它还是通过
===
比较,它都不会'检测已添加的承诺(就像引用在某个时刻发生了更改)。

有趣的是,如果我将

abort
属性公开并在类外调用它,则
queue
方法中的查找可以正常工作:

APIService.queue.push(request);
APIService.abort(request);

但是如果

push
是在
APIService.get
方法内部完成的,则不起作用。我缺少什么?我有什么办法可以理解这种行为吗?

我尝试将

queue
类型扩展为以下内容:

private queue = {
    id: number,
    promise: Promise<boolean>
}[]

并在将新 Promise 添加到

Math.random()
时将
id
作为
queue
传递(以便查看该对象是否未在其他地方实例化),但在
abort
方法中进行查找显示值是一致的(尽管传递的参数仍然不会出现在
this.queue[i].promise
i < this.queue.length
中)。

我还尝试了

setTimeout
,以查看
Promise
参考在状态更改期间是否不会以某种方式发生变化,但我没有观察到任何类似的行为。

现场示例:StackBlitz 演示

javascript reactjs promise
1个回答
0
投票

如果推送是在

APIService.get
方法内部完成的,则不起作用。我错过了什么?

原因是你的

get
方法被声明为
async
,这意味着它创建并返回自己的
Promise
,它包装了函数体的执行。因此,当您在函数内部创建一个 Promise,将其推送到队列,然后
return
它时,所做的就是用显式返回的 Promise 解析外部(隐式)Promise。虽然它们会得到相同的结果,但它们是不同的对象。因此,您可以删除
async
来完成这项工作。

我想按以下方式实现它,其中

APIService.abort
方法应该以
Promise<boolean>
作为参数,在
queue
数组中找到承诺并触发
AbortSignal

无论如何,这并不是中止信号的设计用途。相反,接受中止信号作为

get
方法的参数!在效果中创建一个中止控制器,并传递其信号,然后从效果清理函数中触发它:

useEffect(() => {
    const controller = new AbortController();
    const request = APIService.get(url, data, (response: IResponse) => {
        // Success
    ), (error: IResponseDetails) => {
        // Error
    }, controller.signal);

    return () => {
        controller.abort();
    }
}, []);
© www.soinside.com 2019 - 2024. All rights reserved.