আমি কৌণিকভাবে একটি পর্যবেক্ষণযোগ্য / এইচটিসি / এসিঙ্ক কল থেকে প্রতিক্রিয়াটি কীভাবে ফিরিয়ে দেব?


110

আমার পরিষেবা রয়েছে যা পর্যবেক্ষণযোগ্যকে ফিরিয়ে দেয় যা আমার সার্ভারে একটি http অনুরোধ করে এবং ডেটা পায়। আমি এই ডেটাটি ব্যবহার করতে চাই তবে আমি সবসময়ই শেষ করি undefined। সমস্যা কি?

পরিষেবা :

@Injectable()
export class EventService {

  constructor(private http: Http) { }

  getEventList(): Observable<any>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.get("http://localhost:9999/events/get", options)
                .map((res)=> res.json())
                .catch((err)=> err)
  }
}

উপাদান:

@Component({...})
export class EventComponent {

  myEvents: any;

  constructor( private es: EventService ) { }

  ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
        });

    console.log(this.myEvents); //This prints undefined!
  }
}

আমি পরীক্ষা করেছিলাম কীভাবে আমি একটি অ্যাসিঙ্ক্রোনাস কল থেকে প্রতিক্রিয়া ফিরিয়ে দেব? পোস্ট কিন্তু সমাধান খুঁজে পেল না


2
এটি একটি গুরুত্বপূর্ন বিষয় হতে পারে যে এ্যাসক্রোনাস অপারেশনটিকে একটি সিনক্রোনাস-এ রূপান্তর করা সম্ভব নয় on
n00dl3

@ n00dl3 টিপটির জন্য ধন্যবাদ! "আপনাকে যা করা উচিত নয়:" বিভাগে আমি ব্যাখ্যা করার চেষ্টা করেছি। এটি সম্পাদনা করতে নির্দ্বিধায়।
একো


@ হেরেটিক মনকি যে পোস্টটি ইতিমধ্যে উত্তরে জমা হয়েছে
একো

@ ইকো এবং? এটি কি কোনও সদৃশ প্রশ্নটিকে কম করে দেয়?
হেরেটিক বানর

উত্তর:


117

কারণ:

এর কারণ undefinedহ'ল আপনি একটি অ্যাসিনক্রোনাস অপারেশন করছেন। মানে getEventListপদ্ধতিটি সম্পূর্ণ করতে কিছুটা সময় লাগবে (বেশিরভাগ আপনার নেটওয়ার্কের গতির উপর নির্ভর করে)।

সুতরাং HTTP কল তাকান।

this.es.getEventList()

আপনি আসলে ("আগুন") তৈরি করার পরে আপনার সাথে আপনার এইচটিপি অনুরোধ প্রতিক্রিয়াটির জন্য অপেক্ষাsubscribe করবে । অপেক্ষা করার সময়, জাভাস্ক্রিপ্ট এই কোডের নীচে লাইনগুলি কার্যকর করবে এবং যদি এটি সিঙ্ক্রোনাস অ্যাসাইনমেন্ট / ক্রিয়াকলাপগুলির মুখোমুখি হয় তবে তা তা তত্ক্ষণাত কার্যকর করা হবে।

সুতরাং সাবস্ক্রাইব করার পরে getEventList()এবং প্রতিক্রিয়াটির জন্য অপেক্ষা করার পরে ,

console.log(this.myEvents);

অবিলম্বে লাইন কার্যকর করা হবে। undefinedসার্ভারের কাছ থেকে প্রতিক্রিয়া আসার আগে এবং এর মান হ'ল (বা আপনি এটি প্রথম দিকে যা শুরু করেছেন) তার কাছে।

এটি করার মতো:

ngOnInit(){
    setTimeout(()=>{
        this.myEvents = response;
    }, 5000);

    console.log(this.myEvents); //This prints undefined!
}


সমাধান:

তাহলে আমরা কীভাবে এই সমস্যাটি কাটিয়ে উঠব? আমরা কলব্যাক ফাংশনটি ব্যবহার করব যা subscribeপদ্ধতি। কারণ সার্ভার থেকে ডেটা এলে subscribeএটি প্রতিক্রিয়াটির সাথেই থাকবে।

সুতরাং কোডটি এতে পরিবর্তন করা হচ্ছে:

this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //<-- not undefined anymore
    });

প্রতিক্রিয়া মুদ্রণ করবে .. কিছু সময় পরে।


আপনার কি করা উচিত:

আপনার প্রতিক্রিয়াটির সাথে লগইন করা ছাড়াও অনেকগুলি জিনিস থাকতে পারে; subscribeডেটা এলে আপনার এই সমস্ত অপারেশন কলব্যাকের ভিতরে ( ফাংশনের অভ্যন্তরে) করা উচিত।

আরেকটি বিষয় উল্লেখ করার বিষয় হ'ল আপনি যদি কোনও Promiseপটভূমি থেকে আসেন তবে thenকলব্যাকটি subscribeপর্যবেক্ষণের সাথে মিল রাখে।


আপনার যা করা উচিত নয়:

আপনার একটি সিঙ্ক অপারেশনে অ্যাসিঙ্ক অপারেশন পরিবর্তন করার চেষ্টা করা উচিত নয় (এটি যে আপনি করতে পারেন তা নয়)। আমাদের অ্যাসিঙ্ক অপারেশনগুলির অন্যতম কারণ হ'ল ব্যবহারকারীরা কোনও সময় অপারেশনটি শেষ হওয়ার অপেক্ষায় না রাখে যখন তারা সেই সময়ের মধ্যে অন্যান্য কাজ করতে পারে। মনে করুন যে আপনার একটি অ্যাসিঙ্ক অপারেশন সম্পূর্ণ হতে 3 মিনিট সময় নেয়, যদি আমাদের অ্যাসিঙ্ক অপারেশন না থাকে তবে ইন্টারফেসটি 3 মিনিটের জন্য হিমশীতল হয়ে যায়।


প্রস্তাবিত পড়া:

এই উত্তরের আসল ক্রেডিটটি যায়: আমি কীভাবে একটি অ্যাসিঙ্ক্রোনাস কল থেকে প্রতিক্রিয়া ফিরিয়ে দেব?

তবে কৌণিক 2 প্রকাশের সাথে আমাদের টাইপস্ক্রিপ্ট এবং পর্যবেক্ষণযোগ্যদের সাথে পরিচয় করিয়ে দেওয়া হয়েছিল সুতরাং এই উত্তরটি পর্যবেক্ষণযোগ্যদের সাথে একটি অ্যাসিনক্রোনাস অনুরোধ পরিচালনা করার প্রাথমিক বিষয়গুলি আশাবাদী coversেকে দেয়।


3
পোস্টের ঠিক একই সময়ে যখন কোন প্রশ্নের উত্তর দেওয়া হয় .. পরিবর্তে কোনও ব্লগ পোস্ট থামানো এবং লেখার জন্য এটি ভাল জায়গা
জোনাস প্রিম

3
@ জোনাসপ্রাইম সত্য, তবে স্ট্যাকওভারফ্লোতে জ্ঞান ভাগ করে নেওয়ার ক্ষেত্রে কোনও ভুল নেই। আপনি যেমন ভোটের সংখ্যা দেখছেন, এটি এখানে অনেক লোককে সহায়তা করেছে এবং এটি এখনও অবিরত থাকবে।
অমিত চিগাদানী

11

কৌণিক / জাভাস্ক্রিপ্টে একটি http কল করা অ্যাসিঙ্ক্রোনাস অপারেশন। সুতরাং আপনি যখন এইচটিপি কল করবেন তখন এই কলটি শেষ করতে নতুন থ্রেড বরাদ্দ করা হবে এবং অন্য থ্রেডের সাথে পরের লাইনে কার্যকর করা হবে। এজন্য আপনি অপরিশোধিত মান পাচ্ছেন। এটি সমাধান করতে নীচে পরিবর্তন করুন

this.es.getEventList()  
      .subscribe((response)=>{  
       this.myEvents = response;  
        console.log(this.myEvents); //<-this become synchronous now  
    });

5

আপনি যদি কেবলমাত্র টেমপ্লেটে আমার ইভেন্টগুলি ব্যবহার করেন তবে আপনি অ্যাসিঙ্কপাইপ ব্যবহার করতে পারেন ।

এখানে asyncPipe এবং Angular4 HttpClient উদাহরণ সহ উদাহরণ li


1
এবং (!) এই প্রয়োগের সাথে কারও সাবস্ক্রিপশনটি সাবস্ক্রাইব করার দরকার নেই: মাঝারি.com/@sub.metu/…
সান জে ফ্যালকন

@ সানজেফ্যালকন যেহেতু এটি একটি http অনুরোধ, তাই সাবস্ক্রিপশনের কোনও প্রয়োজন নেই।
AJT82

3

পর্যবেক্ষণগুলি অলস তাই মান পেতে আপনাকে সাবস্ক্রাইব করতে হবে। আপনি আপনার কোডটিতে এটি সঠিকভাবে সাবস্ক্রাইব করেছেন তবে একই সাথে আউটপুটটিকে 'সাবস্ক্রাইব' ব্লকের বাইরে লগ ইন করেছেন। এ কারণেই এটি 'অপরিজ্ঞাত'।

ngOnInit() {
  this.es.getEventList()
    .subscribe((response) => {
        this.myEvents = response;
    });

  console.log(this.myEvents); //Outside the subscribe block 'Undefined'
}

সুতরাং আপনি যদি এটি সাবস্ক্রাইব ব্লকের ভিতরে লগইন করেন তবে এটি প্রতিক্রিয়াটি সঠিকভাবে লগ করবে।

ngOnInit(){
  this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //Inside the subscribe block 'http response'
    });
}

3

এখানে সমস্যা হয়, আপনি আরম্ভের হয় this.myEventsমধ্যে subscribe()যা অ্যাসিঙ্ক্রোনাস ব্লক যখন আপনি করছেন console.log()মাত্র বাইরে subscribe()ব্লক। তাই console.log()আগে কল করা this.myEventsশুরু হয়ে যায়।

সাবস্ক্রাইব () এর অভ্যন্তরে আপনার কনসোল.লগ () কোডটি সরান এবং আপনার কাজ শেষ হয়েছে।

ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
            console.log(this.myEvents);
        });
  }

2

ফলাফল অনির্ধারিত কারণ কৌণিক প্রক্রিয়া async। আপনি নীচের মত চেষ্টা করতে পারেন:

async ngOnInit(){
    const res = await this.es.getEventList();
    console.log(JSON.stringify(res));
}

1

এটি নিশ্চিত করুন যে আপনি কোনও জসন আউটপুটে আপনার প্রতিক্রিয়াটিকে ম্যাপ করেছেন। অন্যথায় এটি সরল পাঠ্য ফিরে আসবে। আপনি এটি এটি এইভাবে করুন:

getEventList(): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });

return this.http.get("http://localhost:9999/events/get", options)
            .map((res)=>{ return res.json();}) <!-- add call to json here
            .catch((err)=>{return err;})
}

1

অপরিজ্ঞাপিত কারণ পরিষেবাটি থেকে কোনও ডেটা উপরের সাবস্ক্রাইব পরিষেবা কল থেকে সেট করার আগে এখানে মানটি লগ হয়। সুতরাং আপনাকে আজাক্স কল শেষ না হওয়া পর্যন্ত এবং প্রতিক্রিয়া ডেটা থেকে ডেটা সেট করতে হবে।

getEventList(): Observable<any>{
    let headers = new Headers({ 'Content-Type': 'application/json' });
    let options = new RequestOptions({ headers: headers });

    return this.http.get("http://localhost:9999/events/get", options)
                .map((res)=> res.json())
                .catch((err)=> err)
  }

এখানে সাবস্ক্রাইব পদ্ধতিতে কনসোল লগ তৈরি করুন যা ডেভেল মাইভেন্য়েট ভেরিয়েবলে সেট করা থাকলে লগটি তৈরি করে।

ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
     // This prints the value from the response
    console.log(this.myEvents)
        }); 
  }

0

আপনি কেবল এই পদ্ধতিটি ব্যবহার করে দেখতে পারেন-

let headers = new Headers({'Accept': 'application/json'});
let options = new RequestOptions({headers: headers});

return this.http
    .get(this.yourSearchUrlHere, options) // the URL which you have defined
    .map((res) => {
        res.json(); // using return res.json() will throw error
    }
    .catch(err) => {
        console.error('error');
    }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.