Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/436.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Node.js是本机Promise.all并行处理还是顺序处理?_Javascript_Node.js_Promise_Es6 Promise - Fatal编程技术网

Javascript Node.js是本机Promise.all并行处理还是顺序处理?

Javascript Node.js是本机Promise.all并行处理还是顺序处理?,javascript,node.js,promise,es6-promise,Javascript,Node.js,Promise,Es6 Promise,我想澄清这一点,因为政府对此不太清楚 Q1:是Promise.all(iterable)按顺序还是并行处理所有承诺?或者,更具体地说,它是否等同于运行像这样的连锁承诺 p1.then(p2).then(p3).then(p4).then(p5).... 或者是另一种算法,所有的p1,p2,p3,p4,p5,等等都同时被调用(并行),并且在所有解析(或一个拒绝)后立即返回结果 Q2:如果Promise.all是并行运行的,那么有没有一种方便的方法可以依次运行iterable 注意:我不想使用Q或

我想澄清这一点,因为政府对此不太清楚

Q1:
Promise.all(iterable)
按顺序还是并行处理所有承诺?或者,更具体地说,它是否等同于运行像这样的连锁承诺

p1.then(p2).then(p3).then(p4).then(p5)....
或者是另一种算法,所有的
p1
p2
p3
p4
p5
,等等都同时被调用(并行),并且在所有解析(或一个拒绝)后立即返回结果

Q2:如果
Promise.all
是并行运行的,那么有没有一种方便的方法可以依次运行iterable

注意:我不想使用Q或Bluebird,而是所有本地ES6规范

Promise.all(iterable)
是否执行所有承诺

不,承诺不能“执行”。它们在创建时就开始执行任务-它们只表示结果-您甚至在将它们传递给
Promise.all
之前就并行地执行所有操作

承诺。所有
只等待多个承诺。它不关心它们的解析顺序,也不关心计算是否并行运行

有没有一种方便的方法可以依次运行iterable

如果你已经有了承诺,你就不能做太多,只能
Promise.all([p1,p2,p3,…])
(它没有顺序的概念)。但是,如果您确实有一组异步函数,那么您确实可以按顺序运行它们。基本上你需要从

[fn1, fn2, fn3, …]

解决方法是使用:


你可以用for循环来做

异步函数返回承诺

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);
}
const createdClientsArray=[];
for(设i=0;i
然后按顺序创建所有客户端


快乐编码:)

只是想详细说明@Bergi的答案(非常简洁,但很难理解;)

此代码将运行数组中的每个项,并将下一个“然后链”添加到末尾

function eachorder(prev,order) {
        return prev.then(function() {
          return get_order(order)
            .then(check_order)
            .then(update_order);
        });
    }
orderArray.reduce(eachorder,Promise.resolve());

希望这是有意义的。

伯吉斯的回答让我使用Array.reduce走上了正确的道路

然而,为了让函数返回我的承诺,一个接一个地执行,我必须添加更多的嵌套

我真正的用例是一个文件数组,由于下游的限制,我需要一个接一个地传输这些文件

这就是我的结局

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(() => {
            return transferFile(theFile); //function returns a promise
        });
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});
如前面的回答所示,使用:

getAllFiles().then( (files) => {
    return files.reduce((p, theFile) => {
        return p.then(transferFile(theFile));
    }, Promise.resolve()).then(()=>{
        console.log("All files transferred");
    });
}).catch((error)=>{
    console.log(error);
});
在开始另一个文件传输之前,没有等待传输完成,而且“已传输的所有文件”文本甚至在第一次文件传输开始之前就出现了

我不确定我做错了什么,但想和大家分享我的工作经验


编辑:自从我写了这篇文章,我现在明白了为什么第一个版本不起作用。then()期望函数返回一个承诺。因此,您应该传入不带括号的函数名!现在,我的函数需要一个参数,所以我需要一个匿名函数,不带参数

您还可以使用递归函数通过异步函数顺序处理iterable。例如,给定一个数组
a
以使用异步函数
someAsyncFunction()
进行处理:

var a=[1,2,3,4,5,6]
函数someAsyncFunction(n){
返回新承诺((解决、拒绝)=>{
设置超时(()=>{
log(“someAsyncFunction:,n)
解析(n)
},Math.random()*1500)
})
}
//您可以使用以下命令按顺序运行每个阵列:
功能顺序(arr,索引=0){
if(index>=arr.length)返回Promise.resolve()
返回someAsyncFunction(arr[index])
.然后(r=>{
log(“获取值:”,r)
返回顺序(arr,索引+1)
})
}
顺序(a)。然后(()=>console.log(“完成”))
并行 优点:速度更快。即使其中一个迭代失败,所有迭代也将开始

依次
for(设i=0;i

优点:循环中的变量可以由每次迭代共享。行为类似于普通的命令式同步代码。

为了解决顺序承诺,我已经使用了of。我不确定这是否有帮助,但这就是我一直在做的

async function run() {
    for (let val of arr) {
        const res = await someQuery(val)
        console.log(val)
    }
}

run().then().catch()

这可能回答了你的部分问题

是的,您可以按如下方式链接一系列承诺返回函数。。。 (这会将每个函数的结果传递给下一个函数)。当然,您可以对其进行编辑,以便将相同的参数(或没有参数)传递给每个函数

功能测试仪1(a){
返回新承诺(功能(完成){
setTimeout(函数(){
完成(a+1);
}, 1000);
})
}
功能测试仪2(a){
返回新承诺(功能(完成){
setTimeout(函数(){
完成(a*5);
}, 1000);
})
}
函数承诺链(参数、列表、结果){
返回新承诺(函数(完成,错误){
var fn=list.shift();
如果(结果==未定义)结果=[];
如果(fn的类型==‘函数’){
fn(参数)。然后(函数(结果){
结果。推(结果);
控制台日志(结果);
承诺链(结果、列表、结果)。然后(完成);
},错误);
}否则{
完成(结果);
}
});
}

promise_chain(0[tester1,tester2,tester1,tester2,tester2]),然后(console.log.bind(console),console.error.bind(console))Bergi的回答帮助我使调用同步。我在下面添加了一个示例,我们在调用前一个函数后调用每个函数

function func1 (param1) {
    console.log("function1 : " + param1);
}
function func2 () {
    console.log("function2");
}
function func3 (param2, param3) {
    console.log("function3 : " + param2 + ", " + param3);
}

function func4 (param4) {
    console.log("function4 : " + param4);
}
param4 = "Kate";

//adding 3 functions to array

a=[
    ()=>func1("Hi"),
    ()=>func2(),
    ()=>func3("Lindsay",param4)
  ];

//adding 4th function

a.push(()=>func4("dad"));

//below does func1().then(func2).then(func3).then(func4)

a.reduce((p, fn) => p.then(fn), Promise.resolve());

使用异步等待可以轻松地按顺序执行一系列承诺:

let a = [promise1, promise2, promise3];

async function func() {
  for(let i=0; i<a.length; i++){
    await a[i]();
  }  
}

func();
let a=[promise1,promise2,promise3]
for (let i = 0; i < items.length; i++) {
    await fetchItem(items[i])
}
async function run() {
    for (let val of arr) {
        const res = await someQuery(val)
        console.log(val)
    }
}

run().then().catch()
function func1 (param1) {
    console.log("function1 : " + param1);
}
function func2 () {
    console.log("function2");
}
function func3 (param2, param3) {
    console.log("function3 : " + param2 + ", " + param3);
}

function func4 (param4) {
    console.log("function4 : " + param4);
}
param4 = "Kate";

//adding 3 functions to array

a=[
    ()=>func1("Hi"),
    ()=>func2(),
    ()=>func3("Lindsay",param4)
  ];

//adding 4th function

a.push(()=>func4("dad"));

//below does func1().then(func2).then(func3).then(func4)

a.reduce((p, fn) => p.then(fn), Promise.resolve());
let a = [promise1, promise2, promise3];

async function func() {
  for(let i=0; i<a.length; i++){
    await a[i]();
  }  
}

func();
/**
 * 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());
};
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 resolveAfterTimeout = async i => {
  return new Promise(resolve => {
    console.log("CALLED");
    setTimeout(() => {
      resolve("RESOLVED", i);
    }, 5000);
  });
};

const call = async () => {
  const res = await Promise.all([
    resolveAfterTimeout(1),
    resolveAfterTimeout(2),
    resolveAfterTimeout(3),
    resolveAfterTimeout(4),
    resolveAfterTimeout(5),
    resolveAfterTimeout(6)
  ]);
  console.log({ res });
};

call();
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();