请稍等 ...
×

采纳答案成功!

向帮助你的同学说点啥吧!感谢那些助人为乐的人

搜索书籍

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

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

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

问题分析:
我觉得出现这样的问题在于点击取消时,没有将已经发送的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()
    }

正在回答 回答被采纳积分+3

1回答

7七月 2019-04-07 18:49:09

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

0 回复 有任何疑惑可以回复我~
  • 提问者 tom睡着了 #1
    好的谢谢老师。如果用我的方式再封上一层promise是不是太复杂了?
    回复 有任何疑惑可以回复我~ 2019-04-07 18:51:02
  • 7七月 回复 提问者 tom睡着了 #2
    还好吧,其实现在小程序通过第三方是可以用async和await的。
    回复 有任何疑惑可以回复我~ 2019-04-07 18:52:04
  • 提问者 tom睡着了 回复 7七月 #3
    嗯好的。
    回复 有任何疑惑可以回复我~ 2019-04-07 18:52:24
问题已解决,确定采纳
还有疑问,暂不采纳
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号