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

纵饮孤独 提交于 2020-04-18 07:25:17

问题


EDIT

I consoled if the script is entering the addHousehold() if condition at:

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)

      }
    })

And it returned the value, but when I intercept it at the main function, it becomes undefined.

END EDIT

Original Post

I have a main function, which loop over an array fromArray, and it takes each row of it and do the following:

  1. add the hoousehold to database using this.api.postData(array);
  2. Enroll into a program program_from
  3. After enrollment, we go into another loop to loop over another array toArray which will contain members, and add members who are related the row fromArray and having the following condition:

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

  4. After adding the related members, we enroll them into another program program_to;

  5. At the end, we take each hh_id and each related mbr_id and connect them through addRelation().

**I. Main Method: **

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);
            }
          }
        })
      }
    });
  }

The main problem now is at this line:

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

the returned value is undefined as it's shown in the image down below:

At the addHousehold() method, it's showing the generated id registered_hh_id:

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

Even at the promise of the function:

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

  }
})

This line is showing the returned ID:

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

So the problem is that inside the add Household method is getting the ID from the server but it's returning it as undefined.

Here are the detailed methods used in the main function as well

II. For the Add household:

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)

      }
    })
  }

**III. Enroll household: **

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;
  }

**IV. After the enroll, we'll add the member: **

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. After adding the member, we enroll it into a program: **

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;
  }

**VI. And at the end we add a relation between the hh_id and all its related 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")
        }
      })

    })
  }

回答1:


You are returning the value using the return keyword in then() callback method of Promises. That won't work. The function you pass inside then() will be executed sometime in the future when the promise is resolved. So if you want to wait will your promise resolves to get the value, use ES6 async-await approach.

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
    }
}

Notice that your function gets prefixed with a keyword called async. This is important if you want to use the await syntax to wait till the promise resolves.

Let's add async-await keywords in main method as well to get the values.

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

Now your main method will also wait till the Promise is resolved and then gets the value which can be used for further processing.

Now in similar fashion, modify other methods as well to wait till the Promise resolves.

For more information on ES6 Promises and async-await keywords, refer this article.



来源:https://stackoverflow.com/questions/60524803/angular-8-why-the-promise-is-returning-an-undefined-value-despite-that-its-prop

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!