Javascript 如何在NodeJs中使一定数量的函数在循环中并行运行?
我正在寻找一种方法,在一个循环中同时运行3个相同的函数,并等待它完成,然后继续运行另外3个相同的函数。我认为它涉及一个循环,promise API。但我的解决办法是失败。如果你能告诉我我做错了什么以及如何修复它,那就太好了 以下是我迄今为止所做的工作:Javascript 如何在NodeJs中使一定数量的函数在循环中并行运行?,javascript,node.js,Javascript,Node.js,我正在寻找一种方法,在一个循环中同时运行3个相同的函数,并等待它完成,然后继续运行另外3个相同的函数。我认为它涉及一个循环,promise API。但我的解决办法是失败。如果你能告诉我我做错了什么以及如何修复它,那就太好了 以下是我迄今为止所做的工作: 我有一个下载功能(调用downloadFile),一个保留功能(调用runAfter)和一个多下载功能(调用downloadList)。它们看起来像这样: const https = require('https') const fs = re
我有一个下载功能(调用
downloadFile
),一个保留功能(调用runAfter
)和一个多下载功能(调用downloadList
)。它们看起来像这样:
const https = require('https')
const fs = require('fs')
const { join } = require('path')
const chalk = require('chalk') // NPM
const mime = require('./MIME') // A small module read Json and turn it to object. It returns a file extension string.
exports.downloadFile = url => new Promise((resolve, reject) => {
const req = https.request(url, res => {
console.log('Accessing:', chalk.greenBright(url))
console.log(res.statusCode, res.statusMessage)
// console.log(res.headers)
const ext = mime(res)
const name = url
.replace(/\?.+/i, '')
.match(/[\ \w\.-]+$/i)[0]
.substring(0, 250)
.replace(`.${ext}`, '')
const file = `${name}.${ext}`
const stream = fs.createWriteStream(join('_DLs', file))
res.pipe(stream)
res.on('error', reject)
stream
.on('open', () => console.log(
chalk.bold.cyan('Download:'),
file
))
.on('error', reject)
.on('close', () => {
console.log(chalk.bold.cyan('Completed:'), file)
resolve(true)
})
})
req.on('error', reject)
req.end()
})
exports.runAfter = (ms, url) => new Promise((resolve, reject) => {
setTimeout(() => {
this.downloadFile(url)
.then(resolve)
.catch(reject)
}, ms);
})
/* The list param is Array<String> only */
exports.downloadList = async (list, options) => {
const opt = Object.assign({
thread: 3,
delayRange: {
min: 100,
max: 1000
}
}, options)
// PROBLEM
const multiThread = async (pos, run) => {
const threads = []
for (let t = pos; t < opt.thread + t; t++) threads.push(run(t))
return await Promise.all(threads)
}
const inQueue = async run => {
for (let i = 0; i < list.length; i += opt.thread)
if (opt.thread > 1) await multiThread(i, run)
else await run(i)
}
const delay = range => Math.floor(
Math.random() * (new Date()).getHours() *
(range.max - range.min) + range.min
)
inQueue(i => this.runAfter(delay(opt.delayRange), list[i]))
}
const multiThread = async (pos, run) => {
const threads = [];
for (let t = 0; t < opt.thread && pos+t < list.length; t++) {
threads.push(run(pos + t));
}
return await Promise.all(threads);
};
显然,downloadList
(multi-thread
)的子函数是一个原因,但我无法读取这些数字(似乎是RAM的物理地址之类的),所以我不知道如何修复它。我不是专业工程师,如果你能给我一个好的解释,我将不胜感激
补充资料:
- NodeJs版本:12.13.1
- 本地主机:Aspire SW3-013>1.9GB(规格为2GB)/Intel Atom CPU Z3735F
- 通过WiFi连接到互联网(Realtek drive)
- 操作系统:Windows 10(无其他选择)
- 为什么要包装
下载文件的承诺?对于进一步的应用,我可以把它放在其他应用程序中,一次只需要下载一次
重要吗?也许没有,只是给自己一点挑战。但如果服务器需要延迟下载时间,它可能会很有用runAfter
- 家庭作业还是生意?没有,只有爱好。我计划构建一个应用程序,从Unsplash的API获取和下载图像。所以我更喜欢一个好的解释我做错了什么以及如何修复它,而不是一个简单的代码
多线程中永不会结束,因为您的继续条件是t
。如果opt.thread
不为零,则将始终为true
。这里有一个无限循环,这就是崩溃的原因
我怀疑你想做这样的事:
const https = require('https')
const fs = require('fs')
const { join } = require('path')
const chalk = require('chalk') // NPM
const mime = require('./MIME') // A small module read Json and turn it to object. It returns a file extension string.
exports.downloadFile = url => new Promise((resolve, reject) => {
const req = https.request(url, res => {
console.log('Accessing:', chalk.greenBright(url))
console.log(res.statusCode, res.statusMessage)
// console.log(res.headers)
const ext = mime(res)
const name = url
.replace(/\?.+/i, '')
.match(/[\ \w\.-]+$/i)[0]
.substring(0, 250)
.replace(`.${ext}`, '')
const file = `${name}.${ext}`
const stream = fs.createWriteStream(join('_DLs', file))
res.pipe(stream)
res.on('error', reject)
stream
.on('open', () => console.log(
chalk.bold.cyan('Download:'),
file
))
.on('error', reject)
.on('close', () => {
console.log(chalk.bold.cyan('Completed:'), file)
resolve(true)
})
})
req.on('error', reject)
req.end()
})
exports.runAfter = (ms, url) => new Promise((resolve, reject) => {
setTimeout(() => {
this.downloadFile(url)
.then(resolve)
.catch(reject)
}, ms);
})
/* The list param is Array<String> only */
exports.downloadList = async (list, options) => {
const opt = Object.assign({
thread: 3,
delayRange: {
min: 100,
max: 1000
}
}, options)
// PROBLEM
const multiThread = async (pos, run) => {
const threads = []
for (let t = pos; t < opt.thread + t; t++) threads.push(run(t))
return await Promise.all(threads)
}
const inQueue = async run => {
for (let i = 0; i < list.length; i += opt.thread)
if (opt.thread > 1) await multiThread(i, run)
else await run(i)
}
const delay = range => Math.floor(
Math.random() * (new Date()).getHours() *
(range.max - range.min) + range.min
)
inQueue(i => this.runAfter(delay(opt.delayRange), list[i]))
}
const multiThread = async (pos, run) => {
const threads = [];
for (let t = 0; t < opt.thread && pos+t < list.length; t++) {
threads.push(run(pos + t));
}
return await Promise.all(threads);
};
这一行是(让t=pos;t
,这是打字错误吗?在你的例子中,t
总是小于opt.thread+t
,这意味着一个无限循环。这是否回答了你的问题:我在循环中犯这样的错误太愚蠢了。在这里,我认为我犯了一些可怕的错误,使用了太多的承诺或其他东西。非常感谢你的良好和明确的解释。