أنجولار - ExpressJS/Typescript - غير قادر على استرجاع قيمة ZoneAwarePromise؟


بدء التحديث 1

المشكلة هي أنني غير قادر على الحصول على كل المدن والمواقع بالترتيب بمجرد أن أقوم برسم FormArray مرة أخرى وهذا بسبب الحلقة فقط. على أي حال، أنا جديد في TypeScript، قد تفهم أفضل. شكراً مرة أخرى.

import { Component, OnInit, NgZone } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { FormBuilder, FormGroup, FormArray, Validators, FormControl } from '@angular/forms';
import { CustomValidators } from 'ng2-validation';
import { SharedService } from '../../../layouts/shared-service';
import { MdSnackBar, MdSnackBarConfig, MdDialog, MdDialogRef, MdDialogConfig } from '@angular/material';
// Added employee services
import { VehiclePlanService } from '../../../service/vehicle-plan.service';
import { PlanService } from '../../../service/plan.service';
import { LocationService } from '../../../service/location.service';
import { VehicleMakeService } from '../../../service/vehicle-make.service';
import { CommonService } from '../../../service/common.service'; // call the common services
import { PlanInterface } from './plans.interface';

import 'rxjs/add/operator/toPromise';

declare var $: any;
@Component({
  selector: 'app-vehicle-plan',
  templateUrl: './vehicle-plan.component.html',
  styleUrls: ['./vehicle-plan.component.scss']
})
export class VehiclePlanComponent implements OnInit {

    pageTitle: "Vehicle Plan";
    _id : string = this.route.snapshot.params['id'];

    public form: FormGroup;

    plansElement = {};   sessionData = {}; activePlans = {}; activeMake = {}; loc = {}; city = {}; locationNames = {};
    activePlanKey = []; activeMakeKey = []; locKey = []; cityKey = []; value = []; planVals = [];
    securityDeposit :  string ; fuleLevel : string; bookinH : string; bookingCycle : string; freeKm : string; grace : string; resVP: string;
    planDetails: string; vehicleDetails: string; vehicleID: string; planID: string; 
    planName: string ; makeName : string;

    constructor(        private fb: FormBuilder,
                        private _sharedService: SharedService, 
                        private router: Router,
                        private route: ActivatedRoute,
                        public snackBar: MdSnackBar,
                        public dialog: MdDialog,
                        private vpService: VehiclePlanService,
                        private plan: PlanService,
                        private locationService: LocationService,
                        private vmService: VehicleMakeService,
                        private commonService : CommonService
                    ) {
                        this._sharedService.emitChange(this.pageTitle);
                        this.commonService.getSession().then((res) => {
                        this.sessionData = res['data'];
                    });
        }

    ngOnInit() {
        this.getActivePlans();
        this.getActiveVehicleMake();
        this.getCityForPlan();
        this.getLocForPlan();
        this.planName= '' ; this.makeName = '';
        this.form = this.fb.group({ 
            plan_name:              [null, Validators.required],
            vehicle_make:           [null, Validators.required],
            rate_per_additional_km: [null, Validators.required],
            rate_per_plan:          [null, Validators.required],
            planArray: this.fb.array([
                this.initPlans([]),
            ])
        })

    }

    // Operate vehiclemake to add / edit
    actionVP(model: PlanInterface) {

        let formData = model["value"];
        var pa = model["value"].planArray;

        for(let i=0; i<pa.length;i++) {
            if(pa[i].location_name != null) {
                let vp = {
                    'vehicle_make': [{
                        "id" : formData.vehicle_make,
                        "make_name" : this.vehicleDetails
                    }],
                    'plan_name': [{
                        "id" : formData.plan_name,
                        "plan_name" : this.planDetails
                    }],
                    'location': [{
                        "id" : "1",
                        "location_name" : pa[i].location_name,
                        "city" : pa[i].city,
                        "lat" : "0.00",
                        "long" : "0.00"
                    }],
                    'plan_rate': (pa[i].rate_plan != null) ? pa[i].rate_plan : formData.rate_per_plan,
                    'total_free_km': (pa[i].total_free_km != null) ? pa[i].total_free_km : this.freeKm,
                    'additional_km_charges': (pa[i].additional_km_charges != null) ? pa[i].additional_km_charges : formData.rate_per_additional_km,
                    'minimum_hours': (pa[i].minimum_hours != null) ? pa[i].minimum_hours : this.bookinH,
                    'booking_cycle': (pa[i].booking_cycle != null) ? pa[i].booking_cycle : this.bookingCycle,
                    'rate_fuel_level': (pa[i].rate_fuel_level != null) ? pa[i].rate_fuel_level : this.fuleLevel,
                    'grace_period': (pa[i].grace_period != null) ? pa[i].grace_period : this.grace,
                    'security_deposit': (pa[i].security_deposit != null) ? pa[i].security_deposit : this.securityDeposit,
                    "organization" : [{
                        "id" : "1",
                        "name" : "Driven"
                    }],
                    'modified_date': new Date()
                };

                // SAVE DATA START
                if(this.route.snapshot.params['id']) {
                    this.updateVP(this.route.snapshot.params['id'], vp);
                } else {
                    this.saveVP(vp);
                }
                // SAVE DATA END

            }
        }
    }

    // Insert data to vehiclemake
    saveVP(vp) {
        // Build data JSON
        vp['created_date'] = new Date();
        this.vpService.saveVehiclePlan(vp).then((result) => {
            let id = result['data']['_id'];
            this.openSnackBar("Saved vehicle plan successfully", "");
            this.router.navigate(['/driven/vehicle-plan']);
        }, (err) => {
            this.openSnackBar("Something went wrong! vehicle plan not saved", "");
            console.log(err);
        });
    }

    // Update vehiclemake details
    updateVP(id, vp) {
        this.vpService.updateVehiclePlan(id, vp).then((result) => {
            let id = result['data']['_id'];
            this.openSnackBar("Updated vehicle plan successfully", "");
            this.router.navigate(['/driven/vehicle-plan']);
        }, (err) => {
            this.openSnackBar("Something went wrong! vehicle plan not updated", "");
            console.log(err);
        });
    }

    // Get the all active plans
    getActivePlans() {
        this.plan.getActivePlans().then((res) => {
         if(res['status'] == 'success'){
            this.activePlans = res['data'];     
            this.activePlanKey = Object.keys(this.activePlans);
          }else{
              this.openSnackBar(res['data']['message'], "");
          }         
        }, (err) => {
                console.log(err);
        });
    }

    // Get the all active plans
    getActiveVehicleMake() {
        this.vmService.getActiveVehicleMake().then((res) => {
         if(res['status'] == 'success'){
            this.activeMake = res['data'];      
            this.activeMakeKey = Object.keys(this.activeMake);
          }else{
              this.openSnackBar(res['data']['message'], "");
          }         
        }, (err) => {
                console.log(err);
        });
    }
    // Get the all Locations for plans gruped by city
    getCityForPlan() {
        this.locationService.getCityForPlan().then((res) => {
         if(res['status'] == 'success'){
            this.city = res['data'];        
            this.cityKey = Object.keys(this.city);
          }else{
              this.openSnackBar(res['data']['message'], "");
          }         
        }, (err) => {
                console.log(err);
        });
    }

    async getLocForPlan() {
        let res = await this.locationService.getLocForPlan();
        if(res['status'] == 'success') {
            this.loc = res['data'];
            this.locKey = Object.keys(this.loc);
            this.addEditValues();
        } else {
            this.openSnackBar(res['data']['message'], "");
        }
    }

    // used to display the alert message 
    openSnackBar(message: string, action: string) {
        this.snackBar.open(message, action, {
            duration: 2000,
        });
    }

    initPlans(planVals) {
        //console.log(planVals);
        return this.fb.group({
            city_name:              [planVals['city_name']],
            city :                  [planVals['city']],
            is_active:              [planVals['is_active']],
            location_name:          [planVals['location_name']],
            rate_plan:              [planVals['rate_plan']],
            total_free_km:          [planVals['total_free_km']],
            additional_km_charges:  [planVals['additional_km_charges']],
            minimum_hours:          [planVals['minimum_hours']],
            booking_cycle:          [planVals['booking_cycle']],
            rate_fuel_level:        [planVals['rate_fuel_level']],
            grace_period:           [planVals['grace_period']],
            security_deposit:       [planVals['security_deposit']]
        });
    }

    addEditValues() {
        let len = this.locKey.length;
        const control = <FormArray>this.form.controls['planArray'];
        if(len) { control.removeAt(0); }
        for(let i=0;i<len;i++) {
            // DEFAULT NULL
            this.planVals['city'] = null;
            this.planVals['location_name'] = null;
            this.planVals['is_active'] = null;
            this.planVals['rate_plan'] = null;
            this.planVals['total_free_km'] = null;
            this.planVals['additional_km_charges'] = null;
            this.planVals['minimum_hours'] = null;
            this.planVals['booking_cycle'] = null;
            this.planVals['rate_fuel_level'] = null;
            this.planVals['grace_period'] = null;
            this.planVals['security_deposit'] = null;
            // DEFAULT NULL
            this.planVals['city_name'] = this.loc[i]._id[0];
            let lenInner = this.loc[i].locations.length;
            for(let k=0;k<lenInner;k++) {
                if(this.loc[i].locations[k].is_active) {
                    // UPDATED DATA FROM DB
                    if(this.planID && this.vehicleID) {
                        this.planVals['city'] = this.loc[i].locations[k].city[0];
                        this.planVals['location_name'] = this.loc[i].locations[k].location_name;
                        this.getVPDetails(this.planID,this.vehicleID,this.planVals['location_name'],this.planVals['city']).then((res: any) => {
                            console.log(res);
                            if(res['status'] == 'success') {
                                if(k==0) {
                                    this.planVals['city_name'] = this.loc[i]._id[0];
                                    control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                                }
                                // FROM DB
                                this.planVals['rate_plan'] = res['data'][0]['plan_rate'];
                                this.planVals['total_free_km'] = res['data'][0]['total_free_km'];
                                this.planVals['additional_km_charges'] = res['data'][0]['additional_km_charges'];
                                this.planVals['minimum_hours'] = res['data'][0]['minimum_hours'];
                                this.planVals['booking_cycle'] = res['data'][0]['booking_cycle'];
                                this.planVals['rate_fuel_level'] = res['data'][0]['rate_fuel_level'];
                                this.planVals['grace_period'] = res['data'][0]['grace_period'];
                                this.planVals['security_deposit'] = res['data'][0]['security_deposit'];
                                // FROM DB
                                this.planVals['city_name'] = null;
                                this.planVals['is_active'] = this.loc[i].locations[k].is_active;
                                this.planVals['city'] = this.loc[i].locations[k].city[0];
                                this.planVals['location_name'] = this.loc[i].locations[k].location_name;
                                control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                            } else {
                                if(k==0) {
                                    this.planVals['city_name'] = this.loc[i]._id[0];
                                    control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                                }
                                // BLANK DATA AT FIRST
                                this.planVals['rate_plan'] = null;
                                this.planVals['total_free_km'] = null;
                                this.planVals['additional_km_charges'] = null;
                                this.planVals['minimum_hours'] = null;
                                this.planVals['booking_cycle'] = null;
                                this.planVals['rate_fuel_level'] = null;
                                this.planVals['grace_period'] = null;
                                this.planVals['security_deposit'] = null;
                                // BLANK DATA AT FIRST
                                this.planVals['city_name'] = null;
                                this.planVals['city'] = this.loc[i].locations[k].city[0];
                                this.planVals['is_active'] = this.loc[i].locations[k].is_active;
                                this.planVals['location_name'] = this.loc[i].locations[k].location_name;
                                control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                            }
                        });
                    } else {
                        if(k==0) {
                            this.planVals['city_name'] = this.loc[i]._id[0];
                            control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                        }
                        // BLANK DATA AT FIRST
                        this.planVals['rate_plan'] = null;
                        this.planVals['total_free_km'] = null;
                        this.planVals['additional_km_charges'] = null;
                        this.planVals['minimum_hours'] = null;
                        this.planVals['booking_cycle'] = null;
                        this.planVals['rate_fuel_level'] = null;
                        this.planVals['grace_period'] = null;
                        this.planVals['security_deposit'] = null;
                        // BLANK DATA AT FIRST
                        this.planVals['city_name'] = null;
                        this.planVals['city'] = this.loc[i].locations[k].city[0];
                        this.planVals['is_active'] = this.loc[i].locations[k].is_active;
                        this.planVals['location_name'] = this.loc[i].locations[k].location_name;
                        control.push(this.initPlans(this.planVals)); //#### PUSH INTO FORMARRAY ####
                    }
                }
            }
        }
    }

    removeFormArray() {
        this.planVals = [];
        const control = <FormArray>this.form.controls['planArray'];
        for (var i = control.length - 1; i > 0; i--) {
            this.removeInput(i);
        }
    }

    removeInput(i: number) {
        const control = <FormArray>this.form.controls['planArray'];
        control.removeAt(i);
    }

    async getVPDetails(pid, vid, locname, cityname): Promise<any> {
        return await this.vpService.getVehiclePlansInfo({plan_id: pid, make_id: vid, loc: locname, city: cityname});
    }

    // used to populate the  default security deposit & fule level
    selectVM(value){
       this.vmService.showVehicleMake(value['value']).then((res) => {           
            this.securityDeposit = res['data']['base_security_deposit'];
            this.fuleLevel = res['data']['rate_per_fuel_level'];
            this.makeName = value['value'];
            this.vehicleID = res['data']['_id'];
            this.vehicleDetails = res['data']['brand_name'] + ' ' + res['data']['make_name'] + ' ' + res['data']['model_name'];
            this.getVehiclePlan();
            return false;
      }, (err) => {
        console.log(err);
      });
    }
    // used to prepopulate the default value min booking h, h/ booking cycle, free km, grace time
    //bookinH : string; bookingCycle : string; freeKm : string; grace : string;
    selectPlan(value) {
        this.plan.getPlansInfo(value['value']).then((res) => {
            this.bookinH = res['data']['min_booking_hours'];
            this.bookingCycle = res['data']['hours_per_booking_cycle'];
            this.freeKm = res['data']['free_km_per_booking_cycle'];
            this.grace = res['data']['grace_period_in_hours'];
            this.planName = value['value'];
            this.planDetails = res['data']['plan_name'];
            this.planID = res['data']['_id'];
            this.getVehiclePlan();
            return false;
      }, (err) => {
        console.log(err);
      });
    }
    // get the all plans on change of plans and vehicle make
    getVehiclePlan(){       
        if(this.planName != ''  && this.makeName != '' ) {
            //const control = <FormArray>this.form.controls['planArray'];
            //control.controls = [];
            this.removeFormArray();
            this.addEditValues();
        }
    }

    // update the plan screen with default values
    updateDefaultValue(){
        var rate_plan = $('.rate_per_plan').val();      var additional_km_charges = $('.rate_per_additional_km').val();
        var security_deposit = this.securityDeposit;    var grace_period = this.grace;        
        var rate_fuel_level = this.fuleLevel;           var booking_cycle = this.bookingCycle;        
        var minimum_hours = this.bookinH;               var total_free_km = this.freeKm;

        $('.security_deposit, .grace_period, .rate_fuel_level, .booking_cycle, .minimum_hours, .additional_km_charges, .total_free_km, .rate_plan').each(function(){
            $('.security_deposit').val(security_deposit);
            $('.grace_period').val(grace_period);
            $('.rate_fuel_level').val(rate_fuel_level);
            $('.booking_cycle').val(booking_cycle);
            $('.minimum_hours').val(minimum_hours);
            $('.additional_km_charges').val(additional_km_charges);
            $('.total_free_km').val(total_free_km);
            $('.rate_plan').val(rate_plan);
        });
        return false;
    }

    checkAllLoc(value){
        var val = $('#'+value).val();
        if(val == "true"){
            $('.'+value).prop('checked', true); 
            $('#'+value).val("false");
        } else {
            $('.'+value).prop('checked', false); 
            $('#'+value).val("true");
        }
    }

    uncheckParent(value){
        $('#'+value).prop('checked', false);
        $('#'+value).val("true");
    }

}

نهاية التحديث 1

أنا أستخدم TypeScript في MeanStack وأستخدم دالة مع async لأنها لم تعمل بالترتيب المتسلسل

// Calling Function (In Main.ts file)
let rs = getVPDetails("2132");

// Function Definition (In Main.ts file)
async getVPDetails(pid) {
    let res = await this.vpService.getPlansInfo({plan_id: pid});
    return res;
}

// Middle Ware (IN service.ts file)
  getPlansInfo(data) {
    return new Promise((resolve, reject) => {
        this.http.post('/vehicle-plan/plan-info', data)
          .map(res => res.json())
          .subscribe(res => {
            resolve(res);
          }, (err) => {
            reject(err);
          });
    });
  }

أنا أحصل على القيمة الدقيقة عند إرجاع res (في "return res;") كما أحتاج. ولكن في rs (حيث أقوم بالاستدعاء)، أحصل على قيمة مثل هذه:

ZoneAwarePromise {__zone_symbol__state: null, __zone_symbol__value: Array(0)}

في __zone_symbol__value لدي بياناتي كما أحتاج لكن بأي حال لا أستطيع الوصول إليها. أعلم أنني أكسر كائن Promise ولكن كيف يمكنني حل ذلك بالضبط عندما لا أريد استخدام then() في getVPDetails();

من فضلك أخبرني بما أفتقده أو كيف يمكنني الحصول على البيانات التي أحتاجها.

شكراً مقدماً.

الإجابة رقم 1

بمجرد أن تضيف async إلى طريقة، ستقوم دائمًا بإرجاع Promise<T>. حيث T هو أي شيء تقوم بإرجاعه، string، void، أو أي شيء آخر.

هذه هي الفكرة كلها من async، والطريقة الوحيدة للحصول على القيمة الصحيحة هي استخدام then. async الخاص بك هنا في الواقع ليس ضروريًا، لأنك تقوم بإرجاع Promise آخر، لكن هذا جانب من الموضوع :)

أفضل شيء هو استخدام تلميحات النوع، وإلا فليس هناك سبب حقيقي لاستخدام TypeScript. بهذه الطريقة يعطيك المُجمّع التلميحات والأخطاء، وستكون قد تم إبلاغك بخطأك:

getVPDetails("2132").then((rs: PlanInfo) => {
    // here you will have your `rs`
});

// Function Definition (using async/await as demonstration)
async getVPDetails(pid): Promise<PlanInfo> {
    return await this.vpService.getPlansInfo({plan_id: pid});
}

// Middle Ware
getPlansInfo(data): Promise<PlanInfo> {
    return this.http.post('/vehicle-plan/plan-info', data)
          .map(res => res.json())
          .toPromise();
}