我想澄清这一点,因为文件不是很清楚;
Q1: Promise.all(iterable)是按顺序还是并行处理所有的promise ?或者,更具体地说,它相当于运行链式承诺
p1.then(p2).then(p3).then(p4).then(p5)....
或者它是某种其他类型的算法,其中所有的p1, p2, p3, p4, p5等同时(并行)被调用,并且结果在所有解决(或一个拒绝)后立即返回?
问题2:如果承诺。所有的运行都是并行的,是否有一种方便的方法来运行一个可迭代对象?
注意:我不想使用Q或蓝鸟,而是所有本地ES6规格。
是的,您可以按照如下方式链接一个promise返回函数数组
(这将每个函数的结果传递给下一个函数)。当然,您可以编辑它,将相同的参数(或不传递参数)传递给每个函数。
function tester1(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a + 1);
}, 1000);
})
}
function tester2(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a * 5);
}, 1000);
})
}
function promise_chain(args, list, results) {
return new Promise(function(done, errs) {
var fn = list.shift();
if (results === undefined) results = [];
if (typeof fn === 'function') {
fn(args).then(function(result) {
results.push(result);
console.log(result);
promise_chain(result, list, results).then(done);
}, errs);
} else {
done(results);
}
});
}
promise_chain(0, [tester1, tester2, tester1, tester2, tester2]).then(console.log.bind(console), console.error.bind(console));
你可以通过for循环来实现。
Async函数返回承诺:
async function createClient(client) {
return await Client.create(client);
}
let clients = [client1, client2, client3];
如果你写下面的代码,那么客户端是并行创建的:
const createdClientsArray = yield Promise.all(clients.map((client) =>
createClient(client);
));
但是如果你想按顺序创建客户端,那么你应该使用for循环:
const createdClientsArray = [];
for(let i = 0; i < clients.length; i++) {
const createdClient = yield createClient(clients[i]);
createdClientsArray.push(createdClient);
}
是的,您可以按照如下方式链接一个promise返回函数数组
(这将每个函数的结果传递给下一个函数)。当然,您可以编辑它,将相同的参数(或不传递参数)传递给每个函数。
function tester1(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a + 1);
}, 1000);
})
}
function tester2(a) {
return new Promise(function(done) {
setTimeout(function() {
done(a * 5);
}, 1000);
})
}
function promise_chain(args, list, results) {
return new Promise(function(done, errs) {
var fn = list.shift();
if (results === undefined) results = [];
if (typeof fn === 'function') {
fn(args).then(function(result) {
results.push(result);
console.log(result);
promise_chain(result, list, results).then(done);
}, errs);
} else {
done(results);
}
});
}
promise_chain(0, [tester1, tester2, tester1, tester2, tester2]).then(console.log.bind(console), console.error.bind(console));
我在尝试解决NodeJS中的一个问题时偶然发现了这个页面:重新组装文件块。基本上:
我有一个文件名数组。
我需要以正确的顺序追加所有这些文件,以创建一个大文件。
我必须异步地做到这一点。
节点的'fs'模块确实提供了appendFileSync,但我不想在此操作期间阻塞服务器。我想用fs。承诺模块,并找到一种方法将这些东西链接在一起。本页上的示例并不适合我,因为我实际上需要两个操作:fsPromises.read()用于读取文件块,fsPromises.appendFile()用于连接到目标文件。也许如果我是更好的JavaScript,我可以使以前的答案为我工作。: -)
我偶然发现了这个,然后我拼凑出了一个可行的解决方案:
/**
* sequentially append a list of files into a specified destination file
*/
exports.append_files = function (destinationFile, arrayOfFilenames) {
return arrayOfFilenames.reduce((previousPromise, currentFile) => {
return previousPromise.then(() => {
return fsPromises.readFile(currentFile).then(fileContents => {
return fsPromises.appendFile(destinationFile, fileContents);
});
});
}, Promise.resolve());
};
这里有一个jasmine单元测试:
const fsPromises = require('fs').promises;
const fsUtils = require( ... );
const TEMPDIR = 'temp';
describe("test append_files", function() {
it('append_files should work', async function(done) {
try {
// setup: create some files
await fsPromises.mkdir(TEMPDIR);
await fsPromises.writeFile(path.join(TEMPDIR, '1'), 'one');
await fsPromises.writeFile(path.join(TEMPDIR, '2'), 'two');
await fsPromises.writeFile(path.join(TEMPDIR, '3'), 'three');
await fsPromises.writeFile(path.join(TEMPDIR, '4'), 'four');
await fsPromises.writeFile(path.join(TEMPDIR, '5'), 'five');
const filenameArray = [];
for (var i=1; i < 6; i++) {
filenameArray.push(path.join(TEMPDIR, i.toString()));
}
const DESTFILE = path.join(TEMPDIR, 'final');
await fsUtils.append_files(DESTFILE, filenameArray);
// confirm "final" file exists
const fsStat = await fsPromises.stat(DESTFILE);
expect(fsStat.isFile()).toBeTruthy();
// confirm content of the "final" file
const expectedContent = new Buffer('onetwothreefourfive', 'utf8');
var fileContents = await fsPromises.readFile(DESTFILE);
expect(fileContents).toEqual(expectedContent);
done();
}
catch (err) {
fail(err);
}
finally {
}
});
});
请看这个示例
的承诺。全部并行工作
const { range, random, forEach, delay} = require("lodash");
const run = id => {
console.log(`Start Task ${id}`);
let prom = new Promise((resolve, reject) => {
delay(() => {
console.log(`Finish Task ${id}`);
resolve(id);
}, random(2000, 15000));
});
return prom;
}
const exec = () => {
let proms = [];
forEach(range(1,10), (id,index) => {
proms.push(run(id));
});
let allPromis = Promise.all(proms);
allPromis.then(
res => {
forEach(res, v => console.log(v));
}
);
}
exec();
NodeJS不是并行运行承诺,而是并发运行,因为它是一个单线程事件循环架构。有可能通过创建一个新的子进程来利用多核CPU来并行运行。
并行Vs并发
其实,什么承诺。所做的就是,将Promise函数堆叠在适当的队列中(参见事件循环架构),并发运行它们(调用P1, P2,…),然后等待每个结果,然后解析Promise。所有的许诺都有结果。
的承诺。所有人都会在第一次承诺时失败,除非你必须自己处理拒绝。
并行和并发有一个很大的区别,第一个会在完全相同的时间在一个单独的进程中运行不同的计算,它们会按照自己的节奏进行,而另一个会一个接一个地执行不同的计算,而不需要等待前一个计算完成并同时进行,而不依赖彼此。
最后,回答你的问题,我保证。所有这些都不是并行或顺序执行,而是并发执行。