代码之家  ›  专栏  ›  技术社区  ›  trebleCode

for循环中的Promise数组-第二次迭代时为空

  •  0
  • trebleCode  · 技术社区  · 4 年前

    我一直在试图理解使用for循环实现一系列承诺的正确方法。在我的代码中,我的数组有3个元素,但它只有第一次通过循环时才有数据。

      private populateRequest(connection: Connection, myArray: any[], containerId: string): Promise<void> {
        // tslint:disable-next-line:no-shadowed-variable
        return new Promise(async (resolve, reject) => {
          const promises: Array<Promise<SomeType>> = [];
          let status = '';
    
          // tslint:disable-next-line:prefer-for-of
          for (let i = 0; i < myArray.length; i++) {
            const data = await this.getResolvedPromise(myArray[i])
            .then(response => response)
            .catch(err => console.log(err));
            if (this.flags.hasOwnProperty('prop1')) {
              status = 'Active';
            } else if (this.flags.hasOwnProperty('prop2')) {
              status = 'Inactive';
            } else if (data[0]['WidgetProp1'] === 'Active') {
              status = 'Inactive';
            } else if (data[0]['WidgetProp1'] === 'Inactive') {
              status = 'Active';
            }
    
            const myMetaObj = {
              prop3: data[0]['WidgetProp3'],
              status
            };
            const myMetaMember = {
              ContainerId: containerId,
              ContentEntityId: data[0]['WidgetId'],
              Body: data[0]['WidgetBody'],
              Metadata: myMetaObj
            };
    
            promises.push(myMetaMember);
          }
    
          Promise.all(promises)
            .then(() => resolve())
            .catch(err => reject(err));
        });
      }
    
      private getResolvedPromise(target: Promise<any>): Promise<any> {
        // tslint:disable-next-line:no-any
        return new Promise((resolve, reject) => {
        // tslint:disable-next-line:no-any
        Promise.all([target])
         .then(() => resolve(target))
         .catch(err => reject(err));
        });
      }
    

    我知道这是因为异步代码和调用没有完成,但不知道为什么我的 Promise.all()

    哈尔普斯?

    0 回复  |  直到 4 年前
        1
  •  2
  •   Bergi    4 年前

    这里有几件事不对。

    首先,你没有把承诺强加给你的朋友 promises 变量。你在推我 myMetaMember 数组中的变量。

    第二,如果您已经在用序列化异步请求 await ,您不需要使用 Promise.all() 完全。

    第三,当您不需要这样做时,通过将现有的承诺包装到手动创建的承诺的附加层中,您使用了几种反模式。

    第四,你一般不想混在一起 等待 .then() .catch() . 从中捕捉错误 ,使用 try/catch . 没有必要这样做 。然后() 因为 已经为你得到了价值。

    第五, getResolvePromise() 似乎做不了什么有用的事。它叫 Promise.all([target]) 然后返回一个承诺 target

    myArray 是一系列的承诺,每一个结果都指向一个对象,以下是我对你所做的最好的解释:

    private populateRequest(connection: Connection, myArray: any[], containerId: string): Promise<Array<{ContainerId: string; ContentEntityId: unknown; Body: unknown; Metadata: {prop3: unknown; status: string}}>> {
          return Promise.all(myArray).then(results => {
              return results.map(data => {
                  let status = '';
                  if (this.flags.hasOwnProperty('prop1')) {
                    status = 'Active';
                  } else if (this.flags.hasOwnProperty('prop2')) {
                    status = 'Inactive';
                  } else if (data[0]['WidgetProp1'] === 'Active') {
                    status = 'Inactive';
                  } else if (data[0]['WidgetProp1'] === 'Inactive') {
                    status = 'Active';
                  }
    
                  const myMetaObj = {
                    prop3: data[0]['WidgetProp3'],
                    status
                  };
                  const myMetaMember = {
                    ContainerId: containerId,
                    ContentEntityId: data[0]['WidgetId'],
                    Body: data[0]['WidgetBody'],
                    Metadata: myMetaObj
                  };
                  return myMetaMember;
              });
          });
      }
    

    我的数组 (您所说的是一个数组或承诺,每个解析到一个对象,您将使用 Promise.all(myArray) . 这将返回一个单独的承诺,该承诺将解析为一个结果数组,然后您可以使用该数组 。然后() 获取结果数组。然后可以迭代该数组,以基于它们的数据构建新对象。

    真的是一系列的承诺,那么你不应该把它说成 myArray: any[]

        2
  •  0
  •   leonat Vinit Sarvade    4 年前

    我真搞不懂你的例子。但我看到你在用 await 同时解决了来自 getResolvedPromise .then 与await结合,await没有意义,因为它做同样的事情,但只是在另一种风格作为“await”。所以你要么:

    const data = await promise;
    // data is resolved here
    

    promise.then(
      data => // data is resolved here
    )
    

    如果必须使用for循环而不是使用 .map 我建议你这样做:

    async someFunction(): Promise<any[]> { 
      promises: Promise<any>[] = []
      for(const value of list) {
        promises.push(new Promise((resolve, reject) => {
          const data = await something
          // do something with data
          const fancyObject = {}
          resolve(fancyObject);
    
      }));
      return Promise.all(promises);
    }
    
    

    您可以看到,依赖于数据对象的逻辑仅在通过 接线员。所以这个逻辑需要用承诺本身来包装。

    Promise.all 在self中,它返回一个Promise,因此您不需要将它包装在另一个Promise中,并解析为包含所有fancyobject的数组。 还要注意,await语法需要try-catch块,以便在promise解析时捕获发生的错误。