搜索书籍

来源:14-12 搜索实现4:动态绑定input输入

tom睡着了

2019-04-07

老师您好,最近又重新看了下这门课程的后几节,发现了一个小问题,以下是我对这个问题的描述和解决方案,不知道是否正确,望指教!

问题描述:
在网络速度不佳的时候,提交搜索后不能及时显示数据,此时点击取消并重新搜索另一个关键字,最终的结果是搜索两个关键字的并集。

问题重现:
先搜索韩寒,立刻点击取消再次搜索金庸,再次点击取消,最后再搜索王小波,出现的结果是三个关键字查询结果的并集。
图片描述

问题分析:
我觉得出现这样的问题在于点击取消时,没有将已经发送的request请求关闭。虽然在代码中已经在每次搜索前清空dataArray,但是由于网络原因过慢,第一次的请求响应会在第三次发送请求后才会回来,所以第一、二、三次的查询结果都会被添加到dataArray中。

我的解决方案:
为promise对象再进行封装,使其能够具备取消功能。

关键代码:

// 在promise对象上进行封装,通过_hasCanceled变量标记其是否已经取消
const makeCancelable = function(promise){
    let _hasCanceled = false
    const wrappedPromise = new Promise((resolve, reject)=>{
        promise.then((res)=>{
            if(_hasCanceled){
	            // 已经取消,调用内部promise对象的reject方法
                reject({isCanceled: true})
            } else {
                resolve(res)
            }
        })
        promise.catch((err)=>{
           if(_hasCanceled) {
               reject({isCanceled: true})
           } else {
               resolve(err)
           }
        })
    })
    return {
        promise: wrappedPromise,
        cancel() {
            _hasCanceled = true;
        }
    }
}

export{
    makeCancelable
}
	// BookModel.js 
    searchWithCancel(start, q) {
        const promise = this.request({
            url: 'book/search?summary=1',
            data: {
                q: q,
                start: start
            }
        })
        return makeCancelable(promise)
    }
	// search component js
	data:{
		// ...
		// 添加一个data,用于触发cancel函数
		searchWithCancel: null
	},
    onConfirm(event) {
	  // ...
      const searchWithCancel = bookModel.searchWithCancel(0, word)
      this.data.searchWithCancel = searchWithCancel
      searchWithCancel.promise
        .then(res => {
          this.setMoreData(res.books)
          this.setTotal(res.total)
          keyworkModel.addToHistory(word)
          this._hideLoadingCenter()
        }).catch(err => {
          console.log(err)
        })
    },
    onCancelSearch() {
	   // 点击取消按钮
      this.data.searchWithCancel.cancel()
      this.initialize()
      this.triggerEvent('cancelSearch', {}, {})
    },
    onClearResult() {
	    // 点击x图标
      this.data.searchWithCancel.cancel()
      this.initialize()
      this._closeResult()
    }
写回答

1回答

7七月

2019-04-07

这里是可能存在这个问题,所以在一次搜索后,需要禁止第二次搜索。也可以把搜索用 一个页面来做,就不会有这个问题。

0
3
tom睡着了
回复
7七月
嗯好的。
2019-04-07
共3条回复

纯正商业级微信小程序应用实战,全方位小程序特性讲解

真实数据的高质量小程序项目,学会直接工作

4782 学习 · 2125 问题

查看课程