أنجولار - 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();
}
