【问题标题】:Do not allow call of a subscriber with the same argument twice until the first is done在第一次完成之前,不允许两次调用具有相同参数的订户
【发布时间】:2018-02-12 15:10:47
【问题描述】:

我目前正在试验信标,我想获得信标的 rssi 测量值以触发警报功能。

我的问题如下:

alarm函数一旦订阅者被触发多次 叫

我想要什么:

不允许alarm 使用前一个参数多次执行。例如,如果使用参数调用警报函数 'x' 然后有人不能用'x' 打电话报警,但可以用 'y' 以避免多次推送到数据库。

我的代码(我使用高贵的信标和我的数据库的火力基地):

// alarm script

import { config, Device, db, auth, productsRef } from './index';
import * as noble from 'noble';
import * as firebase from 'firebase';


var acquiredRef = db.ref('acquired');

function condition(p) {
   // a boolean function that does something


}


function alarm (address) {
  console.log('Alarm!');
  let incident = {
    date : Date(),
    uuid : address,
  }
  db.ref('alarms').push(incident);

}

if (require.main === module) {

  noble.on('stateChange', function (state) {
    if (state === 'poweredOn') noble.startScanning([], true);
    else noble.stopScanning();
  });

  noble.on('discover', function(peripheral) {
    peripheral.address = peripheral.address.toUpperCase();

      if (condition(peripheral)) {
          // query
          acquiredRef.orderByChild('uuid').equalTo(peripheral.address).once('value')
            .then(snap => {
              if(snap.val() == null) alarm(peripheral.address);
            }).catch(err => console.log(err))
      }

  });

}

我尝试使用队列和异步锁但没有成功。它在第一次调用警报时起作用,然后具有与上述相同的行为。

提前致谢

【问题讨论】:

    标签: node.js firebase asynchronous concurrency beacon


    【解决方案1】:

    如果您只想确保警报函数不会在同一行中被调用两次(或更多)次(在这种情况下只是字符串“地址”),您可以只存储一个变量并比较你最近的论点和你当前的论点。如果参数相同,则不要执行函数的其余部分。

    let previousAddress = null;
    function alarm (address) {
      if (address === previousAddress) {
        return; // skip
      }
      console.log('Alarm!');
      let incident = {
        date : Date(),
        uuid : address,
      }
      db.ref('alarms').push(incident);
      previousAddress = address; // update previous argument
    
    }
    

    【讨论】:

      【解决方案2】:

      我遇到了与您类似的问题。

      在我的例子中,一个简单的经过时间变量就可以解决问题。这是必要的,因为发现回调在同一个外围设备上执行了多次。

      看看吧。

      noble.on('discover', function(peripheral) {  
      
        if (peripheral.advertisement.localName == 'FinishLine') {
      
      
            if (lastDetection == null) {
                alert();
            } else {
                if ((Date.now() - lastDetection) / 1000 > 2) {
                    alert();
                }
            }
        } 
      });
      

      由于异步 firebase 调用行为,您不能依赖查询。像我一样暂停 2 秒或更长时间可能会解决您的问题。

      【讨论】:

      • 您好@ctenuta 并为迟到的回复道歉,我在另一个应用程序中使用了您的解决方法,并且非常有用,再次多次推送同一项目。但是,下面给出的解决方案适用于我的服务器端应用程序;我在客户端应用程序中使用了你的!因此,由于我的问题是针对服务器端应用程序,因此我将其他解决方案标记为已接受。再次非常感谢!
      • 你好@bolzano。我懂了。在我的情况下,信标会在一段时间后停止广告,我不需要担心服务器。我想像被接受的解决方案一样的答案,但后来我认为情况并非如此。无论如何,我很高兴能提供帮助,并感谢您支持我的回答。
      • 您的贡献非常有用!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-24
      • 1970-01-01
      • 1970-01-01
      • 2012-04-26
      • 1970-01-01
      • 2014-07-06
      相关资源
      最近更新 更多