Angular 8 为什么 promise 返回一个未定义的值,尽管它在 resolve 之前得到了适当的安慰?

Angular 8 why the promise is returning an undefined value despite that it's properly consoled just before the resolve?

编辑

如果脚本进入 addHousehold() 如果条件为:

addHouseholdPromise.then((res) => {
      console.log("Promise HH: "+res)
      if (res != "add_hh_fail") {
        console.log("success: "+res)
        return res;
      }
      else {
        console.log("fail: "+res)
        // Add to addHousehold array log
        this.addHHArray(row)

      }
    })

并且它返回了值,但是当我在主函数中拦截它时,它变成了undefined

编辑结束

原版Post

我有一个主函数,它遍历数组 fromArray,它获取数组的每一行并执行以下操作:

  1. 使用 this.api.postData(array);
  2. 将家庭添加到数据库
  3. 报名参加计划program_from
  4. 注册后,我们进入另一个循环遍历另一个包含成员的数组 toArray,并添加与行 fromArray 相关且具有以下内容的成员条件:

    if (row_hh['hh_new_id'] == row_mbr['hh_new_id'])

  5. 添加相关成员后,我们将他们注册到另一个程序program_to;

  6. 最后,我们将每个hh_id和每个相关的mbr_id通过addRelation()连接起来。

**我。主要方法:**

uploadDataV3(fromArray, toArray) {

    let workBook = null;
    this.lengthFromArray = fromArray.length;
    this.lengthToArray = toArray.length;
    this.fromArrayUnsuccess = [];
    this.toArrayUnsuccess = [];
    this.arrayOfUnsuccessRelationInsert = [];
    this.fromArrayUnsuccessEnroll = [];
    this.toArrayUnsuccessEnroll = [];
    this.globalArray = [];
    let registered_hh_id = '';
    let registered_mbr_id = '';
    this.relationIDsArray = [];
    let myDate = new Date();
    let enrollDate = this.datePipe.transform(myDate, 'yyyy-MM-dd');
    let hh_id: any = '';
    let mbr_id: any = '';
    fromArray.forEach((row_hh, hh_idx) => {
      // Add household to household entity (table)
      hh_id = this.addHousehold(row_hh);
      console.log('HH ID: '+hh_id)
      // Enroll Household to program_from
      let hh_id_enroll_response = this.enrollHousehold(hh_id, row_hh);
      console.log('Enroll Response: '+hh_id_enroll_response)
      if (hh_id_enroll_response == true) {
        toArray.forEach((row_mbr, mbr_idx) => {
          if (row_hh['hh_new_id'] == row_mbr['hh_new_id']) {
            mbr_id = this.addMember(row_mbr);
            console.log('Member ID: '+mbr_id)
            // Enroll new member id to program_to
            let mbr_id_enroll_response = this.enrollMember(mbr_id, row_mbr);
            if (mbr_id_enroll_response == true) {
              // Add relationship between each household and its related members
              this.addRelation(hh_id, mbr_id);
            }
          }
        })
      }
    });
  }

现在主要问题出在这一行:

hh_id = this.addHousehold(row_hh);
console.log('HH ID: '+hh_id)

返回值为 undefined,如下图所示:

addHousehold()方法中,显示生成的id registered_hh_id:

console.log("check hh_id", this.registered_hh_id);

即使是函数的承诺:

addHouseholdPromise.then((res) => {
  console.log("Promise HH: "+res)
  if (res != "add_hh_fail") {
    return res;
  }
  else {
    // Add to addHousehold array log
    this.addHHArray(row)

  }
})

此行显示返回的 ID:

console.log("Promise HH: "+res)

所以问题是在 add Household 方法中从服务器获取 ID 但它返回的是 undefined

下面还有main函数中使用的详细方法

二.对于添加家庭:

addHousehold(row) {
    console.log(row)

    let addHouseholdPromise = new Promise((resolve, reject) => {
      let attributes = [

        { attribute: "lhMhyp9F1kg", value: row["HH_last_name"] != "" ? row["HH_last_name"] : "" },
        { attribute: "v4nxGLRD3n8", value: row["HH_status"] != "" ? row["HH_status"] : "" },
        { attribute: "rgBt6xSDLPp", value: row["reason_of_inactivation"] != "" ? row["reason_of_inactivation"] : "" },
        { attribute: "w3VYFaC2tnF", value: row["old_lmms_id"] != "" ? row["old_lmms_id"].toString() : "" },
        { attribute: "TN0ZUAIq3jr", value: row["hh_new_id"] != "" ? row["hh_new_id"].toString() : "" },
        { attribute: "g8EjIWItCxm", value: row["registration_date"] != "" ? row["registration_date"] : "" },
      ]
      let data = {
        trackedEntityType: this.formGroup.controls.entity_from.value,
        orgUnit: this.formGroup.controls.organization.value,
        attributes: attributes
      }
      this.registered_hh_id = '';
      this.api.postData(data).subscribe(
        (response_hh) => {
          if (response_hh['httpStatus'] == "OK" && response_hh['httpStatusCode'] == 200 && response_hh['message'] == "Import was successful.") {
            this.registered_hh_id = response_hh['response']['importSummaries'][0]['reference'];
            console.log("check hh_id", this.registered_hh_id);
            resolve(this.registered_hh_id)
          }
          else {
            resolve("add_hh_fail");
          }
        },
        (error_hh) => {
          reject("add_hh_fail");
          console.log(error_hh)
        }
      );
    })
    addHouseholdPromise.then((res) => {
      console.log("Promise HH: "+res)
      if (res != "add_hh_fail") {
        return res;
      }
      else {
        // Add to addHousehold array log
        this.addHHArray(row)

      }
    })
  }

**三。登记家庭:**

enrollHousehold(hh_id, row_hh) {
    let myDate = new Date();
    let result:boolean;
    let enrollDate = this.datePipe.transform(myDate, 'yyyy-MM-dd');
    let enrollHouseholdPromise = new Promise((resolve, reject) => {
      this.api.makeEnrollment(hh_id,
        this.formGroup.controls.program_from.value, "ACTIVE",
        this.formGroup.controls.organization.value,
        enrollDate, enrollDate)
        .subscribe(
          (response_hh_enroll) => {
            if (response_hh_enroll['httpStatus'] == "OK" && response_hh_enroll['httpStatusCode'] == 200 && response_hh_enroll['message'] == "Import was successful.") {
              resolve("hh_enroll_success");
            }
            else {
              reject("hh_enroll_fail");
              // this.addHHArrayEnroll(row_hh)
            }
          },
          (error_hh_enroll) => {
            console.log(error_hh_enroll);
            // this.addHHArrayEnroll(row_hh)
            reject("hh_enroll_fail")
          }
        )
    })
    enrollHouseholdPromise.then((res) => {
      if (res == "hh_enroll_success") {
        result = true;
      }
      else {
        this.addHHArrayEnroll(row_hh);
        result = false;
        // Add to logs
      }
    })

    return result;
  }

**四。注册后,我们将添加成员:**

addMember(row_mbr) {
    let mbr_attributes = [

      { attribute: "TN0ZUAIq3jr", value: row_mbr["hh_new_id"].toString() },
      { attribute: "YvQdThw2NdW", value: row_mbr["mbr_new_id"].toString() },
      { attribute: "jQrM04xaPxb", value: row_mbr["first_name"] != "" ? row_mbr["first_name"] : "" },
      { attribute: "CybsW0GygpD", value: row_mbr["last_name"] != "" ? row_mbr["last_name"] : "" },
      { attribute: "RwRUmhHpSKS", value: row_mbr["father_name"] != "" ? row_mbr["father_name"] : "" },
      { attribute: "wXbpKsIbSRH", value: row_mbr["mother_full_name"] != "" ? row_mbr["mother_full_name"] : "" },
      { attribute: "CtJzimjQTYJ", value: row_mbr["gender"] != "" ? row_mbr["gender"] : "" },
      { attribute: "CtWcqFJCFXV", value: row_mbr["relation_to_HH"] != "" ? row_mbr["relation_to_HH"] : "" },
      { attribute: "qaOqvRz6TNb", value: row_mbr["DOB"] != "" ? this.datePipe.transform(row_mbr["DOB"], "yyyy-MM-dd") : "" },
      { attribute: "lTjjW15jAmv", value: row_mbr["phone_number"] != "" ? row_mbr["phone_number"].toString() : "" },
      { attribute: "CGjfVDBVlqV", value: row_mbr["nationality"] != "" ? row_mbr["nationality"] : "" },
      { attribute: "yo33iKOsHfN", value: row_mbr["other_nationality"] != "" ? row_mbr["other_nationality"] : "" },
      { attribute: "lk1jkG6UK6a", value: row_mbr["unhcr_exists"] != "" ? row_mbr["unhcr_exists"] : "" },
      { attribute: "XskAQYfw4sx", value: row_mbr["unhcr_id"] != "" ? row_mbr["unhcr_id"] : "" },
      { attribute: "Olq1PTOXLSb", value: row_mbr["other_gov_id"] != "" ? row_mbr["other_gov_id"] : "" },
      { attribute: "E63TvSeUUnl", value: row_mbr["other_gov_id_number"] != "" ? row_mbr["other_gov_id_number"] : "" },
      { attribute: "v4nxGLRD3n8", value: row_mbr["mbr_status"] != "" ? row_mbr["mbr_status"] : "" },
      { attribute: "RbXBwAN4Fbq", value: row_mbr["reason_inactive"] != "" ? row_mbr["reason_inactive"] : "" },
      { attribute: "EN5E32lCYNa", value: row_mbr["coordinates"] },
      { attribute: "cWXekTraGOx", value: row_mbr["comments"] != "" ? row_mbr["comments"].toString() : "" }
    ]
    let mbr_data = {
      trackedEntityType: this.formGroup.controls.entity_to.value,
      orgUnit: this.formGroup.controls.organization.value,
      attributes: mbr_attributes
    }

    let addMemberPromise = new Promise((resolve, reject) => {
      this.api.postData(mbr_data).subscribe(
        (response_mbr) => {
          if (response_mbr['httpStatus'] == "OK" && response_mbr['httpStatusCode'] == 200 && response_mbr['message'] == "Import was successful.") {
            this.registered_mbr_id = response_mbr['response']['importSummaries'][0]['reference'];
            resolve(this.registered_mbr_id);
          }
          else {
            resolve("add_mbr_fail");
          }
        },
        (error_mbr) => {
          reject("add_mbr_fail");
          console.log(error_mbr)
        }
      );
    });
    addMemberPromise.then((res) => {
      if (res != "add_mbr_fail") {
        return res;
      }
      else {
        // Add to logs array
        this.addMbrArray(row_mbr);
      }
    })
  }

**V。添加成员后,我们将其注册到一个程序中:**

enrollMember(mbr_id, row_mbr) {
    let myDate = new Date();
    let result:boolean;
    let enrollDate = this.datePipe.transform(myDate, 'yyyy-MM-dd');

    let enrollMemberEnroll = new Promise((resolve, reject) => {
      this.api.makeEnrollment(mbr_id, this.formGroup.controls.program_to.value,
        "ACTIVE", this.formGroup.controls.organization.value,
        enrollDate, enrollDate)
        .subscribe(
          (response_mbr_enroll) => {
            if (response_mbr_enroll['httpStatus'] == "OK" && response_mbr_enroll['httpStatusCode'] == 200 && response_mbr_enroll['message'] == "Import was successful.") {
              resolve("mbr_enroll_success");
            }
            else {
              resolve("mbr_enroll_fail")
            }

          },
          (error_mbr_enroll) => {
            reject("mbr_enroll_fail");
            console.log(error_mbr_enroll)
          }
        );
    });
    enrollMemberEnroll.then((res) => {
      if (res == "mbr_enroll_success") {
        result = true;
      }
      else {
        // Add to enroll logs
        this.addMbrArrayEnroll(row_mbr);
        result = false;
      }
    })

    return result;
  }

**六。最后我们在 hh_id 和所有相关的 mbr_id 之间添加一个关系:**

addRelation(hh_id, mbr_id) {
    let myDate = new Date();
    let enrollDate = this.datePipe.transform(myDate, 'yyyy-MM-dd');
    let checkExistingRelationshipsPromise = new Promise((resolve, reject) => {
      this.api.existingRelationships(hh_id, this.formGroup.controls.program_from.value).subscribe(
        (relation) => {
          console.log(relation, relation['relationships'].length, this.relations)
          // if (relation['httpStatusCode'] == 200 && relation['httpStatus'] == 'OK') {
          if (relation['relationships'].length > 0) {


            this.relations = relation['relationships']

            resolve('relation_exists')
          }
          else {
            this.relations = [];
            resolve('no_relations')
          }

        }, (error) => {
          reject("rejected")
          console.log("relations api: " + error)
        })
    });
    checkExistingRelationshipsPromise.then((res) => {
      if (res == "rejected") {
        console.log("error occured while getting existing relations")
      }
      else {
        console.log(hh_id, mbr_id)


      }

      let addRelationshipPromise = new Promise((resolve, reject) => {
        let programOwners = [{
          ownerOrgUnit: this.formGroup.controls.organization.value,
          program: this.formGroup.controls.program_from.value,
          trackedEntityInstance: hh_id
        }];
        let relationships: any[] = []
        if (res == "relation_exists") {
          this.relations.forEach((val, idx) => {
            relationships.push(val)
          })
          // relationships.push(this.relations)
          console.log(relationships)
        }
        relationships.push(
          {
            lastUpdated: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
            created: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
            relationshipName: "LBN_HH_MBR_Relationship",
            bidirectional: false,
            relationshipType: this.formGroup.controls.relation_id.value,
            // relationship: "wMECqtsc47R",
            from: {
              trackedEntityInstance: {
                trackedEntityInstance: hh_id,
                programOwners: []
              }
            },
            to: {
              trackedEntityInstance: {
                trackedEntityInstance: mbr_id,
                programOwners: []
              }
            },
            // relationshipType: this.formGroup.controls.relation_id.value
          }
        );

        let data = {
          created: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
          orgUnit: this.formGroup.controls.organization.value,
          createdAtClient: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
          trackedEntityInstance: hh_id,
          lastUpdated: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
          trackedEntityType: this.formGroup.controls.entity_from.value,
          lastUpdatedAtClient: this.datePipe.transform(myDate, 'yyyy-MM-ddTHH:mm:ss'),
          inactive: false,
          deleted: false,
          featureType: "NONE",
          programOwners: programOwners,
          relationships: relationships
          // attributes: attributes
        }
        this.relationIDsArray.push(
          {
            hh_id: hh_id,
            mbr_id: mbr_id,
            data: data
          }
        )
        // this.addRelation(response_hh['response']['importSummaries'][0]['reference'], response_mbr['response']['importSummaries'][0]['reference'], data);
        this.api.addRelation(hh_id, data).subscribe(
          (response_relation) => {
            if (response_relation['httpStatusCode'] == 200 && response_relation['httpStatus'] == "OK"
              && response_relation['message'] == 'Import was successful.') {
              resolve("relation added");
            }
            else {
              resolve("relation was not added");
              this.addUnsuccessRelationInsert(hh_id,
                mbr_id,
                this.formGroup.controls.entity_from.value, this.formGroup.controls.organization.value, this.formGroup.controls.relation_id.value)
            }

          },
          (error) => {
            console.log(error);
            this.addUnsuccessRelationInsert(hh_id,
              mbr_id,
              this.formGroup.controls.entity_from.value, this.formGroup.controls.organization.value, this.formGroup.controls.relation_id.value)
            return false;
          }

        );

      })
      addRelationshipPromise.then((res) => {
        if (res == "relation added") {
          console.log("Relation Added")
        }
        else {
          console.log("Error while adding the relationship")
        }
      })

    })
  }

您正在 return 使用 Promise 的 then() 回调方法中的 return 关键字获取值。那行不通的。您在 then() 中传递的函数将在未来的某个时间在解决承诺时执行。因此,如果您想等待您的 promise 解析以获取值,请使用 ES6 async-await 方法。

async addHousehold(row) {
    console.log(row)

    let addHouseholdPromise = new Promise((resolve, reject) => {
      // Your logic goes here
    };

    // Continue your logic but don't call then() method on your promise. Instead let's wait till your promise resolves
    let res = await addHouseholdPromise;
    console.log("Promise HH: "+res)
    if (res != "add_hh_fail") {
      return res;
    }
    else {
      // Add to addHousehold array log
      this.addHHArray(row)

      // return something for else case as well
    }
}

请注意,您的函数以名为 async 的关键字为前缀。如果您想使用 await 语法等待 promise 解析,这很重要。

让我们在 main 方法中添加 async-await 关键字来获取值。

async uploadDataV3(fromArray, toArray) {
  // your logic goes here
  let res = await this.addHousehold(row);
  console.log('result: ', res);
}

现在你的 main 方法也会等到 Promise 被解析,然后获取可用于进一步处理的值。

现在以类似的方式,修改其他方法,等待 Promise 解析。

有关 ES6 Promises 和 async-await 关键字的更多信息,请参阅此 article