收藏
回答

小程序如何维护一个队列,并在处理完一个数据后,再取下一个数据处理?

典型应用场景:

支付成功后,对支付结果进行语音播报:xxx 已支付 100 元。

已有部分解决方案:

https://developers.weixin.qq.com/miniprogram/dev/wxcloud/guide/database/realtime.html

云数据库支持数据库数据变化监听,可以返回新增的订单记录。

在监听到订单后,需要调用txttospeech播放语音,但是语音播放是有处理时间的,比如播放需要2秒,那么就会出现同一时间播放多条语音。如下代码:

我的想法是对data中的orders进行监听,处理一个去拿一个,但是要阻塞监听。

const watcher = db.collection('order')
      // 按 progress 降序
      .orderBy('modified', 'desc')
      // 取按 orderBy 排序之后的前 10 个
      // .limit(10)
      .where({
        sid: sid,
        modified: _.gt(new Date()),
        status: 'DAIZHIFU'
      })
      .watch({
        onChange: function (snapshot) {
          if (snapshot.type === 'init') {
            console.log('data type : ' + snapshot.type)
          } else {
            let hasNewOrder = false
            const orders = _this.data.orders
            var plugin = requirePlugin("WechatSI")
            for (const docChange of snapshot.docChanges) {
              switch (docChange.queueType) {
                case 'enqueue': {
                  console.log("new order wxOrder = " + docChange.doc.wxOrder)
                  hasNewOrder = true
                  orders.unshift(docChange.doc)
                  console.log('orders : ', orders)
                  var sfname = docChange.doc.sfname
                  var price = docChange.doc.price // 分
                  const fenStr = '00' + Number.parseInt(price.toString()).toString()
                  var priceYuan = Number.parseFloat(fenStr.replace(/^(\d+?)(\d{2})$/g, '$1.$2'))
                  var text = sfname + "收款" + priceYuan + "元"


                  // let manager = plugin.getRecordRecognitionManager()
                  plugin.textToSpeech({
                    lang: "zh_CN",
                    tts: true,
                    content: text,
                    success: function (res) {
                      console.log("succ tts", res.filename)
                      // 播放声音
                      var mp3 = res.filename
                      var audio = wx.createInnerAudioContext()
                      audio.src = mp3
                      audio.autoplay = true
                      audio.onPlay(() => {
                        console.log('开始播放')
                      })
                      audio.onError((res) => {
                        console.log(res.errMsg)
                        console.log(res.errCode)
                      })
                    },
                    fail: function (res) {
                      console.log("fail tts", res)
                      wx.showModal({
                        showCancel: false,
                        title: 'TTS Fail',
                        content: JSON.stringify(res)
                      })
                    }
                  })
                }
              }
            }
            _this.setData({
              orders: orders,
              hasNewOrder: hasNewOrder
            })
            if (_this.data.hasNewMessage) {
              _this.scrollToBottom()
            }
          }


        },
        onError: function (err) {
          console.error('the watch closed because of error', err)
          wx.showModal({
            showCancel: false,
            title: '提示',
            content: JSON.stringify(err)
          })
        }
      })
回答关注问题邀请回答
收藏

1 个回答

  • 老张
    老张
    2021-07-26

    onChange里不播放,仅把结果放在一个队列里;

    另一个进程轮询处理这个队列,处理完一条清除,再处理下一条;

    2021-07-26
    有用
    回复 1
    • 李刚
      李刚
      2021-07-26
      谢谢回答。我的问题就是该怎么去轮询数组。onChange里我已经把order放入数组了。hasNewOrder = true; orders.unshift(docChange.doc),逻辑上需要一个线程去处理这个数组,我担心两个问题:1、如果轮询的话,会不会阻塞界面渲染;2、轮询如果能解决,性能会不会很差。
      2021-07-26
      回复
登录 后发表内容