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

前端 - uniapp 中使用getAPP 创建了全局变量,值是一个类实例,更改属性之后getAPP获取不到最新的值?

秦渝
2024-02-06

uniapp 中使用getAPP 创建了全局变量,值是一个类实例,更改属性之后getAPP获取不到最新的值?

我写了一个限制请求数量的类文件,在getAPP中创建这个实例,然后加入方法,然后再获取请求的数量,数量一直是0,没有更新。

/** *@description *@author cy *@date 2022-10-20 09:52 **/export class LimitRequest {  private limit: number = 1; // 限制并发数量  private currentSum: number = 0; // 当前发送数量  private requests: Array<any> = []; // 请求  constructor(limit: number) {    this.limit = limit;    this.currentSum = 0;    this.requests = [];  }  public request(reqFn: Function) {    if (!reqFn || !(reqFn instanceof Function)) {      console.error('当前请求不是一个Function', reqFn);      return;    }    this.requests.push(reqFn);    if (this.currentSum < this.limit) {      this.run();    }  }  public stop() {    this.requests = [];    this.currentSum = 0;  }    public getParam() {        return { currentSum: this.currentSum, requests: this.requests.length };    }  async run() {    try {      ++this.currentSum;      const fn = this.requests.shift();      await fn();            console.error('this.requests', this.requests.length);    } catch (err) {      console.log('Error', err);    } finally {      --this.currentSum;      if (this.requests.length > 0) {        this.run();      }    }  }}

加入request方法模拟请求,

    globalData: {            limitAjax: new LimitRequest(10)        },    for (let i = 0; i < 20; i++) {                getApp().globalData.limitAjax.request(() => {                                        setTimeout(() => {                        let params = getApp().globalData.limitAjax.getParam();                        console.error('parma', params);                    }, 1000)                })            }

打印中的request.length 一直是0,这是为什么呢?求助
image.png

共有2个答案

相俊迈
2024-02-06

因为调用 request 时传入的方法没有返回 Promise

for (let i = 0; i < 20; i++) {  getApp().globalData.limitAjax.request(() => {    return new Promise((resolve) => {      setTimeout(() => {        let params = getApp().globalData.limitAjax.getParam();        console.error("parma", params);        resolve();      }, 1000);    });  });}
林修雅
2024-02-06

这个问题发生的原因是JavaScript中的闭包和异步操作。在JavaScript中,函数是一级对象,这意味着函数可以作为其他函数的参数传递,并且可以作为其他函数的返回值。当你在LimitRequest类的request方法中返回一个函数时,这个函数会捕获到request方法执行时的环境,并记住这个环境。这就是所谓的闭包。

在你的代码中,你创建了一个闭包,它引用了LimitRequest类的requests数组。然后你开始在for循环中创建请求,每个请求都是一个闭包。当你在异步函数中(如setTimeout)使用这些闭包时,它们仍然引用了创建它们的上下文,即LimitRequest类的实例。

然而,当你更改LimitRequest实例的状态(如调用stop方法清空requests数组)时,这个状态更改并不会影响到已经创建的闭包。因为闭包已经捕获了request方法执行时的requests数组的状态,而这个状态在闭包创建后就不会再改变。所以,当你尝试获取请求数量时,你看到的是0,因为闭包引用的requests数组仍然是空的。

要解决这个问题,你需要确保在每次请求时都创建一个新的LimitRequest实例,而不是共享同一个实例。这样,每个请求都有自己的状态,不会受到其他请求的影响。

例如,你可以将创建实例的代码移到request方法中:

for (let i = 0; i < 20; i++) {  getApp().globalData.limitAjax.request(() => {    const limitAjax = new LimitRequest(10);    setTimeout(() => {      let params = limitAjax.getParam();      console.error('parma', params);    }, 1000);  });}

这样,每个闭包都会捕获到它自己的LimitRequest实例的状态,而不是共享同一个实例的状态。这样,你就可以正确地获取到每个请求的参数了。

 类似资料:
  • 问题内容: 我刚刚创建了angularJS应用程序。 这是我的 index.html app.js 我有login.html,register.html和forgotpassword.html,home.html。每个人在单独的文件中都有单独的控制器。login.js,register.js,forgot.js,home.js。 login.js 同样,我在其他控制器中也有post方法。 我想要的

  • 问题内容: 我了解的这段代码。我们复制A并将其称为C。当A更改时,C保持不变 但是当A是一个数组时,我们会有不同的情景。C不仅会改变,而且甚至在我们碰到A之前都会改变 有人可以解释第二个示例中发生的情况吗? 问题答案: Pointy的答案有很好的信息,但这不是此问题的正确答案。 OP所描述的行为是一个错误的一部分,该错误于2010年3月首次报告,并于2012年8月为Webkit进行了修补,但截至本

  • 这段代码我懂。我们复制a并称之为C。当a被改变时,C保持不变 但是当A是一个数组时,我们有一个不同的判断。不仅C会改变,它甚至在我们接触A之前就改变了 有人能解释一下第二个例子中发生了什么吗?

  • 当你使用了一个未知的变量名,通常 JavaScript 会自动创建全局变量: function f() { foo = 123 } f() foo 123 好在你会在 ECMAScript5 的严谨模式得到警告[1]: function f() { 'use strict'; foo = 123 } f() ReferenceError: foo is not defined 参考 [1] Jav

  • 检索给定节点resp的所有属性名(而不是属性值!)的Xpath表达式看起来如何。xml标签? 假设以下XML文档: Xpath//title/@*会选择“eng,fr,easyreading”,但哪个Xpath会选择“lang,lang,type”?

  • 问题 你想创建一个新的拥有一些额外功能的实例属性类型,比如类型检查。 解决方案 如果你想创建一个全新的实例属性,可以通过一个描述器类的形式来定义它的功能。下面是一个例子: # Descriptor attribute for an integer type-checked attribute class Integer: def __init__(self, name):