qq小游戏发布的踩坑日记(一)

资源请求

这阵子要发布qq小游戏了 , 没想到刚上来就翻车了...直接请求资源的时候就炸了:

报错如下:

image.png

VM696:263 createDownloadTask:fail exceed max download connection count

查了下文档 , 说是一次请求不能超过10个...(资源超过10M的一般都超过10个吧??);

各种找, 最后还是得去微信小程序社区找方案, 兜兜转转又跑去github弄了个轮子,

简而言之就是做个队列, 反正每次请求不能超过10个,超过了就老实呆着排队,等一下再说:

最大并发限制10个

并发限制文档传送门

先上github上面轮子的链接:

wx-queue 轮子传送门

嗯...这个轮子有点古老,不能直接用, 而且是用在微信小程序上面的, 所以我得改造一下,废话少说上代码:

//index.js
  import q from './queue'

  function queueRequest(request, concurrency = 10) {

    if (typeof request !== 'function') {

        throw Error('request must be function')

    }

    const queue = q((task, callback) => task(callback), concurrency)

    return (obj) => {

        queue.push((callback) => {

            const originComplete = obj.complete

            obj.complete = (...args) => {

                callback()

                if (typeof originComplete === 'function') {

                    originComplete(...args)

                }

            }

            request(obj)

        })

    }

}
//在老轮子的基础上,在这里加了点东西,因为是downloadFile不给力...qq小游戏的api跟微信部分的是通用的,你懂的,顺手一起弄上去了
  function queue(concurrency) {

    const request = wx.request

    Object.defineProperty(wx, 'request', {

        get() {

            return queueRequest(request, concurrency)

        }

      })

    const QQrequest =qq.request;

    Object.defineProperty(qq, 'request', {

        get() {

            return queueRequest(QQrequest, concurrency)

        }

    })

    const wxDownloadFile = wx.downloadFile ;

    Object.defineProperty(wx, 'downloadFile', {

        get() {

            return queueRequest(wxDownloadFile, concurrency)

        }

    })

    const qqDownloadFile = qq.downloadFile ;

    Object.defineProperty(qq, 'downloadFile', {

        get() {

            return queueRequest(qqDownloadFile, concurrency)

        }

    })

  }

  export {

    queueRequest,

    queue,

  }

然后在打包好的 小游戏项目里面的 game.js (因为是小游戏,所以是game.js,如果是小程序,那就应该是app.js)里面,加上这么两句调用一下:

//game.js 
import { queue } from './queue/index.js'
queue(10);

嗯哼,这样就大功告成啦,但是每次打包完都要手动复制和加那么两句话,实在是让人无语,本着程序猿懒惰的美德, 再弄个自动复制粘贴添加两行代码的 python 文件:

##copyqueue.py  说明一下, 这里是用的python3 
import os, shutil
from os import path

def copyFiles(source, target):
    if source is None or source is "":
        raise FileNotFoundError("源文件夹不能为空")
    if not path.exists(target):
        os.makedirs(target)  # 创建目标文件夹
    if path.isfile(source):  # 源目录是文件
        shutil.copy(source, target)
    else:
        target = path.join(target, path.split(source)[1])
        if not path.exists(target):
            os.makedirs(target)  # 创建目标文件夹
        for file in os.listdir(source):
            newFile = path.join(source, file)
            if path.isfile(newFile):
                shutil.copy(newFile, target)
            else:
                copyFiles(newFile, target)

target = 'F:\\*****\\wechatgame' #此处星号为省略路径,用你自己的真实路径就好了
source = 'F:\\*****\\queue' #此处星号为省略路径,用你自己的真实路径就好了

copyFiles(source,target)

# coding=UTF-8
filename = 'F:\\*****\wechatGame\\game.js'#此处星号为省略路径,用你自己的真实路径就好了

with open(filename, 'a') as file_object:
    file_object.write("\n\n")
    file_object.write("import { queue } from './queue/index.js'\n")
    file_object.write("queue(9);\n")

嗯哼,然后打包成exe 或者直接弄个bat文件执行以下 , 就ok了,下次双击就可以了~ ~(或者你其实也可以弄个插件,打包的时候顺便打包进去,时间有限我就不赘述啦);

想了想,我还是干脆把另外一个文件也copy进来给大家好了,到时候直接复制粘贴就能用了这轮子:

//queue.js
const checkConcurrency = (concurrency = 1) => {
    if (concurrency == null) {
        concurrency = 1
    }
    else if (concurrency === 0) {
        throw new Error('Concurrency must not be zero')
    }
    return concurrency
}

const onlyOnce = (fn) => (...args) => {
    if (fn === null) {
        throw new Error('Callback was already called')
    }
    const callFn = fn
    fn = null
    return callFn(...args)
}

export default function queue(callback, concurrency) {
    checkConcurrency(concurrency)

    // 待处理的队列
    let workers = []
    // 正在处理的队列
    const workerList = []

    return {
        concurrency,
        push(task, callback) {
            workers.push({
                task,
                callback,
            })
            setTimeout(() => {
                this.process()
            }, 0)
        },
        process() {
            while (this.concurrency > workerList.length && workers.length) {
                const worker = workers.shift()
                workerList.push(worker)
                callback(worker.task, onlyOnce((...args) => {
                    this.pull(worker)
                    if (typeof worker.callback === 'function') {
                        worker.callback(...args)
                    }
                    this.process()
                }))
            }
        },
        pull(worker) {
            const index = workerList.indexOf(worker)
            if (index !== -1) {
                workerList.splice(index, 1)
            }
        }
    }
}
 

好了,今天先到这儿了,有什么疑问的话欢迎随时交流~ 谢谢!! (另外,您有空也可以 上github的原轮子主人那里点个星星,哈哈哈哈,饮水不忘挖井人嘛~)

祝安好~ ~ O(∩_∩)O

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容