Funktsiyani faqat bitta chaqiriq to'plamiga bir marta chaqirish mumkinmi?

Keling, har bir mijozning ma'lumotlari o'zgarganida o'z mijozlariga ma'lumotlarni yuboradigan serverim borligini aytaylik. Mijozlar sinfi shunga o'xshash:

function Client() {
    this.data = {};
    this.update = function (key, value) {
        this.data[key] = value;
        this.emitUpdate();
    };

    this.emitUpdate = function() {
       //tell server to send this client's data
    };
}

var myClient = new Client();

Agar bitta narsani o'zgartirsam:

myClient.update("name", "John");

server ushbu mijozning yangi ma'lumotlari bilan barcha mijozlarni yangilaydi. Ajoyib.

Lekin ...

Agar ilovamdagi turli joylardan bir nechta narsani o'zgartirsam:

if (something === true) {
    myClient.update("something", true);
} else {
    myClient.update("something_else", true);
}

myClient.update("age", Date.now());

har doim o'zgargan ikkita narsa bo'ladi va emitUpdate() ikki marta chaqiriladi. Server ikki marta ma'lumotlarni yuboradi va barcha mijozlar uni ikki marta bajarishi kerak. Buning 100 ta o'zgarishini tasavvur qiling ... Bu o'zgarish bir vaqtning o'zida amalga oshirilganligi sababli, server yangilanishni faqat bir marta yuborishi mumkinligini inobatga olsak, katta xarajat bo'ladi.

emitUpdate() ni qanday qilib chaqiraman? Men underscore.js dan foydalangan holda defer() va gaz kelebeği() vazifalari. Muammo shundaki, ularning ta'siri birlashtirilishi kerak.

var log = function() {
  console.log("now");
};

// logs "now" 10 times
for (let i = 0; i < 10; i++) {
  _.defer(log);
}

// logs "now" 10 times
var throttled = _.throttle(log, 0);
for (let i = 0; i < 10; i++) {
  throttled();
}

kutish kabi 1 yoki 2 kabi turli xil miqdorda throttle() foydalanayotgan bo'lsangiz, natijalar barqaror emas - ba'zan u bir marta, ba'zan esa ko'proq.

Menga shunga o'xshash narsa kerak:

// logs "now" once
var magic = _.deferottle(log);
for (let i = 0; i < 10; i++) {
  magic();
}

Bunga erishishim mumkinmi?

1
Nima uchun faqat update dan emitUpdate ajratib olmang va avvalgiga kerakli deb ayting?
qo'shib qo'ydi muallif hindmost, manba
Nima uchun faqat update dan emitUpdate ajratib olmang va avvalgiga kerakli deb ayting?
qo'shib qo'ydi muallif hindmost, manba
O'zgarishlarni tarqatish uchun yangilanishlar oxirida nima uchun da'vo qilmang? underscorejs.org/#debounce
qo'shib qo'ydi muallif corn3lius, manba
O'zgarishlarni tarqatish uchun yangilanishlar oxirida nima uchun da'vo qilmang? underscorejs.org/#debounce
qo'shib qo'ydi muallif corn3lius, manba

6 javoblar

Aslida gaz kelishi shart emas, faqatgina defer ni ishlatib, ba'zi boolean bayroq tekshirishlari bilan bog'lang.

Shunga o'xshash narsa:

this.update = function (key, value) {
    this.data[key] = value;
    if (this.isQueued) return;
    this.isQueued = true;
    _.defer(function() {
        this.isQueued = false;
        this.emitUpdate();
    }.bind(this));
};
2
qo'shib qo'ydi
Siz bu tushunchaning ma'nosi bilan bir xil ekanligini anglaysiz, faqat pastki chiziqqa va 14 daqiqadan keyin bog'liqlikka bog'liq.
qo'shib qo'ydi muallif idbehold, manba

Aslida gaz kelishi shart emas, faqatgina defer ni ishlatib, ba'zi boolean bayroq tekshirishlari bilan bog'lang.

Shunga o'xshash narsa:

this.update = function (key, value) {
    this.data[key] = value;
    if (this.isQueued) return;
    this.isQueued = true;
    _.defer(function() {
        this.isQueued = false;
        this.emitUpdate();
    }.bind(this));
};
2
qo'shib qo'ydi
Siz bu tushunchaning ma'nosi bilan bir xil ekanligini anglaysiz, faqat pastki chiziqqa va 14 daqiqadan keyin bog'liqlikka bog'liq.
qo'shib qo'ydi muallif idbehold, manba

Bu update() usuliga bir nechta sinxronlashtirilgan qo'ng'iroqlar uchun ishlashi kerak:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="true"> <div class="snippet-code">

function Client() {
  this.data = {};
  this.update = function (key, value) {
    this.data[key] = value;
    if (!this.aboutToUpdate) {
      this.aboutToUpdate = setTimeout(() => {
        this.aboutToUpdate = false
        this.emitUpdate()
      })
    }
  };

  this.emitUpdate = function() {
   //tell server to send this client's data
    console.log('update sent', this.data)
  };
}

// This should only log 'update sent' once
var client = new Client()
for (var i = 0; i < 5; i++) {
  client.update(i, i)
}
</div> </div>
1
qo'shib qo'ydi

Bu update() usuliga bir nechta sinxronlashtirilgan qo'ng'iroqlar uchun ishlashi kerak:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="true"> <div class="snippet-code">

function Client() {
  this.data = {};
  this.update = function (key, value) {
    this.data[key] = value;
    if (!this.aboutToUpdate) {
      this.aboutToUpdate = setTimeout(() => {
        this.aboutToUpdate = false
        this.emitUpdate()
      })
    }
  };

  this.emitUpdate = function() {
   //tell server to send this client's data
    console.log('update sent', this.data)
  };
}

// This should only log 'update sent' once
var client = new Client()
for (var i = 0; i < 5; i++) {
  client.update(i, i)
}
</div> </div>
1
qo'shib qo'ydi

Dush berayotganda boshimga bir yechim tashlandi:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

var deferottle = function(func) {
  var called, args, ctx;

  return function() {
    args = arguments;
    ctx = this;

    if (!called) {
      called = true;
      setTimeout(function() {
        func.apply(ctx, args);
        called = false;
      });
    }
  };
};

var magic = deferottle(function(num) {
  console.log("num: ", num);
});

for (let i = 0; i < 10; i++) {
  magic(i);
}
</div> </div>

0 kuting bilan debounce() ni o'chirib qo'yadi > Quyidagida ham foydalanish mumkin:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

var magic = _.debounce(function(num) {
  console.log("num: ", num);
}, 0);

for (let i = 0; i < 10; i++) {
  magic(i);
}
<script src="http://underscorejs.org/underscore-min.js"></script>
</div> </div>
0
qo'shib qo'ydi
Bu sizning muammoingizni hal qilmaydi, chunki u faqat so'nggi qo'ng'iroqni tarqatadi. Misol uchun, myClient.update ("something_else", true); myClient.update ("yosh", Date.now ()); faqat yosh kalitini yangilaydi.
qo'shib qo'ydi muallif idbehold, manba
Ha, mening javobimning birinchi qismida ishlamaydi, lekin bu ikkinchi qismning echimi. Pastki chiziqning debounce() ilovasini amalga oshirish, aslida deferottle() funktsiyasiga o'xshaydi. Bunga ishora qilganingiz uchun tashakkur!
qo'shib qo'ydi muallif Hristiyan Dodov, manba
savol ning birinchi qismini nazarda tutdim. Va qo'shimcha vergulim bor.
qo'shib qo'ydi muallif Hristiyan Dodov, manba

Dush berayotganda boshimga bir yechim tashlandi:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

var deferottle = function(func) {
  var called, args, ctx;

  return function() {
    args = arguments;
    ctx = this;

    if (!called) {
      called = true;
      setTimeout(function() {
        func.apply(ctx, args);
        called = false;
      });
    }
  };
};

var magic = deferottle(function(num) {
  console.log("num: ", num);
});

for (let i = 0; i < 10; i++) {
  magic(i);
}
</div> </div>

0 kuting bilan debounce() ni o'chirib qo'yadi > Quyidagida ham foydalanish mumkin:

<div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"> <div class="snippet-code">

var magic = _.debounce(function(num) {
  console.log("num: ", num);
}, 0);

for (let i = 0; i < 10; i++) {
  magic(i);
}
<script src="http://underscorejs.org/underscore-min.js"></script>
</div> </div>
0
qo'shib qo'ydi
Bu sizning muammoingizni hal qilmaydi, chunki u faqat so'nggi qo'ng'iroqni tarqatadi. Misol uchun, myClient.update ("something_else", true); myClient.update ("yosh", Date.now ()); faqat yosh kalitini yangilaydi.
qo'shib qo'ydi muallif idbehold, manba
Ha, mening javobimning birinchi qismida ishlamaydi, lekin bu ikkinchi qismning echimi. Pastki chiziqning debounce() ilovasini amalga oshirish, aslida deferottle() funktsiyasiga o'xshaydi. Bunga ishora qilganingiz uchun tashakkur!
qo'shib qo'ydi muallif Hristiyan Dodov, manba
savol ning birinchi qismini nazarda tutdim. Va qo'shimcha vergulim bor.
qo'shib qo'ydi muallif Hristiyan Dodov, manba
Javascript UZB
Javascript UZB
99 ishtirokchilar

@js_uzb @vuejs_uz @react_uz @nodejs_uz @angular_uz @ngTashkent @yiiframework_uz @laravel_uz @linux_uzbek @python_uz @swift_uzb —————— @uzdevgroup @UzGeeksGroup ——— @UzDev_Jobs @jobs_uzb