جاوااسکریپت - جایگزینی setTimeout() در یک فرم واکنشی انگولار با یک Observable


من میخواهم setTimeout() را با یک Observable در یک فرم واکنشی Angular جایگزین کنم.

من یک کامپوننت نوه دارم که بخشی از یک فرم واکنشی بزرگتر را ارائه میدهد، یک آرایه از اشیاء داده را از یک نقطه پایانی API دریافت میکند، آن دادهها را در یک آرایه فرم بستهبندی میکند و آن را به فرم ارسال میکند. این به خوبی کار میکند.

مشکل این است که ماهیت غیرهمزمان نقاط پایانی API ما باعث میشود دادههای فرم این کامپوننت نوه قبل از اینکه دادههای جدید بتوانند خود را راهاندازی کنند و دادههای قدیمی را پاک کرده و دادههای جدید را دوباره پر کنند، دادههای قدیمی را رندر کنند. ما این مشکل را با استفاده از setTimeout() به مدت ۵۰۰ میلیثانیه حل کردهایم. این در سمت فرانتاند به خوبی کار میکند.

مشکل این است که setTimeout() باعث ایجاد مشکلاتی در تستهای e2e ما میشود زیرا قبل از بارگذاری دادهها، تست را کامل میکند. علاوه بر این، استفاده از timeout راهحل طولانیمدتی برای این مسئلهی async نیست... به خصوص اگر دادهها گاهی طولانیتر از ۱/۲ ثانیه طول بکشند (که مورد معمول نیست، اما کاملاً ممکن است).

من امیدوارم که زمانسنج خود را با یک observable جایگزین کنم به عنوان یک راه حل بهتر که تستهای ما را مسدود نکند و بتواند به طور ایمنتری با عملیات ناهمزمان برخورد کند. مشکل این است که نمیتوانم observable را راهاندازی کنم و هنوز مبتدی RxJS هستم.

در اینجا تابع اصلی با زمانسنجی که در حال حاضر در حال اجرا است آمده است:

setTimeout(() => {
      this.dataRow = [];
      for (let item of this.data.row) {
        this.dataRow.push(item);
      }
    }, 500);

اینجا تلاش من برای بازسازی با یک Observable است:

this.dataRow = [];
   this.dataEmitter = from(this.data.row).pipe(delay(1000)).subscribe(data => this.dataRow.push(data);)

کدم یک جریان داده ایجاد میکند، اما به نظر نمیرسد که مثل تایماوت کار کند. چگونه میتوانم این کار را انجام دهم؟ آیا این اصلاً روش درستی برای مواجهه با این مشکل است؟

پاسخ شماره ۱

ویرایش :

this.dataEmitter = of(this.data.row).pipe(delay(1000)).subscribe(row => {
  for (let item of row) {
    this.dataRow.push(item);
  }
}

delay(1000) به ازای هر ارسال، 1 ثانیه تأخیر ایجاد میکند. و قطعه کد شما درست نیست - شما نمیتوانید push(row) کنید چون row مقدار undefined دارد (همانطور که در قطعه کد مشاهده میشود).

پس اگر this.data.row یک شیء باشد، شما نیاز دارید آن را به صورت قابل تکرار (مثل یک آرایه) تبدیل کنید اگر بخواهید this.data.row را به صورت «قطعهقطعه» ارسال کنید.

اما اگر فقط میخواهید از setTimeout خلاص شوید:

this.dataEmitter = from([this.data.row]).pipe(delay(1000)).subscribe(row => {
  for (let item of row) {
    this.dataRow.push(item);
  }
}

پاسخ شماره ۲

کد شما به این صورت خواهد بود:

this.dataRow = []

of(this.data.row)
 .pipe(delay(500))
 .subscribe(data => {
   for(let item of data) {
     this.dataRow.push(item);
   }
 })