当前位置: 首页 > 知识库问答 >
问题:

避免显式传递“this”上下文的方法?

尉迟越
2023-03-14

在开发新产品时,我创建了一个后端和前端项目。对于前端,我使用带有Typescript的角度框架。下面是一个问题,因为我对这门语言还不熟悉(几天前)。我的问题是关于回调以及如何避免“this”上下文中的显式传递。我已经阅读了一些资源,我将链接它们。

下面我将为HttpClient实现一个包装器。快速版本是使用插件架构(由角度路由支持)的模块进行流控制,最好是通过使用观察员和订阅者广播401之类的错误以实现优雅的重新进入(在我看来)-我们不会讨论这个问题,但提到上下文可能会有所帮助。

下面是我的代码的基本部分:包装器=

export class WebService {

  constructor(private httpClient: HttpClient,
              private exceptionService: ExceptionService<Exception>) { }

  public post<T>(url: string, dataToPost: any, callBack: (responseData: T) => 
                void, callBackInstance: any): void {

    this.httpClient.post<T>(url, dataToPost).subscribe(
      (data: T) =>  {
        callBack.call(callBackInstance, data);
      },

      (error: HttpErrorResponse) => {
        this.exceptionService.notify(error);
      }
    );

现在,我可以使用显式管理回调的“this”上下文。调用()以插入它。我不介意在您的任何建议中使用它-但是查看签名,您会发现该方法要求您在所需的“this”上下文中传递(callbackInstance)。这就把一些责任推到了我不想要的方法调用方身上。对我来说,一个类非常像一个以“this”作为初始置换的数组——因为我正在为回调传递方法;是否真的没有办法检查该方法以得出适当的“this”?大致如下:callbackInstance=callback。getRelativeContext();回拨。调用(回调实例、数据);这将消除额外的参数,使我的团队使用的方法不那么容易出错。

欢迎链接到参考资料,但如果可能,请尽量缩小到相关部分。

链接:

用于更新“this”上下文

参数回调

编辑:从我导出并放置在测试用例中的已接受答案:

const simpleCallback = (response) => {holder.setValue(response); };
service.post<LoginToken>(Service.LOGIN_URL, '', simpleCallback);

共有1个答案

闾丘京
2023-03-14

如果需要将上下文传递给回调,那么回调本身将依赖于该上下文:

function explicitContext(callback, context) {
    const arg = 1;
    callback.call(context, arg);
}

function implicitContext(callback) {
    const arg = 1;
    const someCleverContext = {importantVal: 42, importantFunc: () => {}};
    callback.call(someCleverContext, arg);
}

如果我们需要实际访问回调中的上下文,请考虑使用情况:

function explicitUsage() {
    const someCleverContext = {importantVal: 42, importantFunc: () => {}};
    const callback = function(arg) {this.importantFunc(arg);}
    explicitContext(callback, someCleverContext);
}

function implicitUsage() {
    const callback = function(arg) {this.importantFunc(arg);}
    implicitContext(callback);
}

在这两种情况下,我们实际上都在泄露上下文的细节,并迫使消费者承担一些责任!现在,如果我们真的需要传递上下文,没有一种神奇的方法可以绕过它。好消息是,我们可能一开始就不需要传递上下文。

export class WebService {

    constructor(
        private httpClient: HttpClient,
        private exceptionService: ExceptionService<Exception>)
    { }

    public post<T>(url: string, dataToPost: any, callBack: (responseData: T) => void): void {

        this.httpClient.post<T>(url, dataToPost).subscribe(
            (data: T) => {
                callBack(data);
            },

            (error: HttpErrorResponse) => {
                this.exceptionService.notify(error);
            },
        );
    }
}

通过这种方式,我们可以让客户机代码只关心responseData,如果他们需要一些巧妙的上下文,他们可以自行绑定它:

function usage() {
    let webService: WebService;
    const simpleCallback = (response) => {console.log(response);} // can inline too
    webService.post('/api', {data: 1}, simpleCallback);

    const cleverContextCallback = function(response) {this.cleverLog(response)};
    const cleverContext = {cleverLog: (data) => console.log(data)};
    const boundCallback = cleverContextCallback.bind(cleverContext);
    webService.post('/api', {data: 1}, boundCallback );
}

说了这么多,我肯定会建议从您的服务中返回可观察到的。

export class WebService {

    constructor(
        private httpClient: HttpClient,
        private exceptionService: ExceptionService<Exception>)
    { }

    public post<T>(url: string, dataToPost: any, callBack: (responseData: T) => void): Observable<T> {

        const observable = this.httpClient.post<T>(url, dataToPost);
        // Note that httpClient.post automatically completes.
        // If we were using some other library and we would want to close the observable ourselves,
        // you could close the observable yourself here after one result:

        if ('we need to close observable ourselves after a result') {
            return observable.pipe(take(1));
        }

        if ('we need to handle errors') {
            return observable.pipe(
                catchError(error => {
                    this.exceptionService.notify(error);
                    if ('We can fallback') {
                        return of('Fallback Value');
                    } else {
                        throw new Error('OOPS');
                    }
                }),
            );
        }

        return observable;
    }
}

处理服务内部的错误、关闭和其他杂务将让服务的消费者专注于来自响应的数据。

 类似资料:
  • 我正在尝试将一个项目迁移到Android Room。阅读了Android Room文档后,我注意到Singleton适合访问我的数据库。 Android开发者的报价: 注意:如果您的应用程序在单个进程中运行,则在实例化AppDatabase对象时应遵循单例设计模式。每个RoomDatabase实例都相当昂贵,您很少需要在单个进程中访问多个实例。 我编写了以下代码: 只是一个简单的双重检查锁定单例。

  • 问题内容: 如何传递上下文?我想打电话,如果在1000毫秒。我怎样才能做到这一点? 当我尝试上述操作时,指的是窗口。 问题答案: 编辑: 总而言之,早在2010年,当有人问这个问题时,解决此问题的最常用方法是保存对进行函数调用的上下文的引用,因为执行函数时要指向全局对象: 在一年前发布的ES5规范中,它引入了该方法,但最初的答案中并未建议使用该方法,因为该方法尚未得到广泛支持,您需要使用polyf

  • 问题内容: 上周受本文启发,我正在重构我必须更明确地将上下文(数据库池,会话存储等)传递给处理程序的应用程序。 但是,我遇到的一个问题是,如果没有全局模板映射,我的自定义处理程序类型(要满足)上的方法将无法再访问该映射以呈现模板。 我需要保留全局变量,或者将我的自定义处理程序类型重新定义为结构。 有没有更好的方法来实现这一目标? func.go struct.go 有没有更干净的方法将实例传递给?

  • 本文向大家介绍JS中this上下文对象使用方式,包括了JS中this上下文对象使用方式的使用技巧和注意事项,需要的朋友参考一下 JavaScript 有一套完全不同于其它语言的对 this 的处理机制。 在五种不同的情况下 ,this 指向的各不相同。 有句话说得很在理 -- 谁调用它,this就指向谁 一、全局范围内 在全局范围内使用this ,它将指向全局对象(浏览器中为 window) 二、

  • 问题内容: 每当关于Java同步的问题浮出水面时,有些人就会很想指出应该避免的事情。他们声称,取而代之的是,最好是锁定私有引用。 给出的一些原因是: 一些邪恶的代码可能会窃取你的锁(非常流行,也有一个“偶然”的变体) 同一类中的所有同步方法都使用完全相同的锁,这会降低吞吐量 你(不必要地)暴露了太多信息 包括我在内的其他人则认为,这是一个惯用语言(在Java库中也是如此),是安全且易于理解的。应当

  • 问题内容: 最近,我开始修补React.js,我喜欢它。我开始使用常规的ES5,以便掌握所有内容,所有文档均使用ES5编写… 但是现在我想尝试一下ES6,因为它有光泽而且是新的,而且似乎确实简化了某些事情。让我感到困扰的是,对于我添加到组件类中的每个方法,现在都必须将“ this”绑定到该方法,否则它将无法正常工作。所以我的构造函数最终看起来像这样: 如果我要在类中添加更多方法,这将变得更大,更难