资源请求
这阵子要发布qq小游戏了 , 没想到刚上来就翻车了...直接请求资源的时候就炸了:
报错如下:
VM696:263 createDownloadTask:fail exceed max download connection count
查了下文档 , 说是一次请求不能超过10个...(资源超过10M的一般都超过10个吧??);
各种找, 最后还是得去微信小程序社区找方案, 兜兜转转又跑去github弄了个轮子,
简而言之就是做个队列, 反正每次请求不能超过10个,超过了就老实呆着排队,等一下再说:
并发限制文档传送门
先上github上面轮子的链接:
嗯...这个轮子有点古老,不能直接用, 而且是用在微信小程序上面的, 所以我得改造一下,废话少说上代码:
//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