Vic*_*huk 347 javascript asynchronous node.js ecmascript-6 babeljs
据我所知,在ES7/ES2016中,将多个await代码放在代码中将类似于.then()使用promise 进行链接,这意味着它们将一个接一个地执行,而不是在并行执行.所以,例如,我们有这个代码:
await someCall();
await anotherCall();
Run Code Online (Sandbox Code Playgroud)
我是否理解正确,anotherCall()只有在someCall()完成后才会被调用?并行调用它们的最优雅方式是什么?
我想在Node中使用它,所以也许有一个async库的解决方案?
编辑:我对这个问题中提供的解决方案不满意:由于异步生成器中的非并行等待承诺而减速,因为它使用生成器而我正在询问更一般的用例.
mad*_*ox2 536
你可以在Promise.all()上等待:
await Promise.all([someCall(), anotherCall()]);
Run Code Online (Sandbox Code Playgroud)
Hav*_*ven 98
TL; DR
使用Promise.all时发生错误的并行函数调用,答案的行为不正确.
首先,立即执行所有异步调用并获取所有Promise对象.二,使用await的Promise对象.这样,当您等待第一个Promise解析其他异步调用时,仍然在进行中.总的来说,只有最慢的异步调用才会等待.例如:
// Begin first call and store promise without waiting
const someResult = someCall();
// Begin second call and store promise without waiting
const anotherResult = anotherCall();
// Now we await for both results, whose async processes have already been started
const finalResult = [await someResult, await anotherResult];
// At this point all calls have been resolved
// Now when accessing someResult| anotherResult,
// you will have a value instead of a promise
Run Code Online (Sandbox Code Playgroud)
JSbin示例:http://jsbin.com/xerifanima/edit?js,console
警告:await只要第一次await调用在所有异步调用之后发生,调用是在同一行还是在不同的行上都无关紧要.见JohnnyHK的评论.
更新:这个回答有错误处理根据不同的时机@ BERGI的答案,但它不是为发生错误扔出去的错误,但毕竟承诺执行.我将结果与@ jonny的提示进行比较:[result1, result2] = Promise.all([async1(), async2()]),检查以下代码片段
const correctAsync500ms = () => {
return new Promise(resolve => {
setTimeout(resolve, 500, 'correct500msResult');
});
};
const correctAsync100ms = () => {
return new Promise(resolve => {
setTimeout(resolve, 100, 'correct100msResult');
});
};
const rejectAsync100ms = () => {
return new Promise((resolve, reject) => {
setTimeout(reject, 100, 'reject100msError');
});
};
const asyncInArray = async (fun1, fun2) => {
const label = 'test async functions in array';
try {
console.time(label);
const p1 = fun1();
const p2 = fun2();
const result = [await p1, await p2];
console.timeEnd(label);
} catch (e) {
console.error('error is', e);
console.timeEnd(label);
}
};
const asyncInPromiseAll = async (fun1, fun2) => {
const label = 'test async functions with Promise.all';
try {
console.time(label);
let [value1, value2] = await Promise.all([fun1(), fun2()]);
console.timeEnd(label);
} catch (e) {
console.error('error is', e);
console.timeEnd(label);
}
};
(async () => {
console.group('async functions without error');
console.log('async functions without error: start')
await asyncInArray(correctAsync500ms, correctAsync100ms);
await asyncInPromiseAll(correctAsync500ms, correctAsync100ms);
console.groupEnd();
console.group('async functions with error');
console.log('async functions with error: start')
await asyncInArray(correctAsync500ms, rejectAsync100ms);
await asyncInPromiseAll(correctAsync500ms, rejectAsync100ms);
console.groupEnd();
})();Run Code Online (Sandbox Code Playgroud)
Jon*_*ter 81
更新:
原始答案使得正确处理承诺拒绝变得困难(在某些情况下是不可能的).正确的解决方案是使用Promise.all:
const [someResult, anotherResult] = await Promise.all([someCall(), anotherCall()]);
Run Code Online (Sandbox Code Playgroud)
原始答案:
只需确保在等待其中任何一个之前调用这两个函数:
// Call both functions
const somePromise = someCall();
const anotherPromise = anotherCall();
// Await both promises
const someResult = await somePromise;
const anotherResult = await anotherPromise;
Run Code Online (Sandbox Code Playgroud)
use*_*596 17
没有Promise.all()的另一种方法是并行执行:
首先,我们有2个打印数字的功能:
function printNumber1() {
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log("Number1 is done");
resolve(10);
},1000);
});
}
function printNumber2() {
return new Promise((resolve,reject) => {
setTimeout(() => {
console.log("Number2 is done");
resolve(20);
},500);
});
}
Run Code Online (Sandbox Code Playgroud)
这是顺序的:
async function oneByOne() {
const number1 = await printNumber1();
const number2 = await printNumber2();
}
//Output: Number1 is done, Number2 is done
Run Code Online (Sandbox Code Playgroud)
这是并行的:
async function inParallel() {
const promise1 = printNumber1();
const promise2 = printNumber2();
const number1 = await promise1;
const number2 = await promise2;
}
//Output: Number2 is done, Number1 is done
Run Code Online (Sandbox Code Playgroud)
Ale*_*sko 11
就我而言,我有几个要并行执行的任务,但我需要对这些任务的结果做一些不同的事情。
function wait(ms, data) {
console.log('Starting task:', data, ms);
return new Promise(resolve => setTimeout(resolve, ms, data));
}
var tasks = [
async () => {
var result = await wait(1000, 'moose');
// do something with result
console.log(result);
},
async () => {
var result = await wait(500, 'taco');
// do something with result
console.log(result);
},
async () => {
var result = await wait(5000, 'burp');
// do something with result
console.log(result);
}
]
await Promise.all(tasks.map(p => p()));
console.log('done');
Run Code Online (Sandbox Code Playgroud)
和输出:
Starting task: moose 1000
Starting task: taco 500
Starting task: burp 5000
taco
moose
burp
done
Run Code Online (Sandbox Code Playgroud)
小智 8
等待 Promise.all([someCall(), anotherCall()]); 正如已经提到的,它将充当线程围栏(在并行代码如 CUDA 中很常见),因此它将允许其中的所有承诺运行而不会相互阻塞,但会阻止执行继续,直到所有承诺都得到解决。
另一种值得分享的方法是 Node.js 异步,如果任务直接与 API 调用、I/O 操作等有限资源的使用相关,它还可以让您轻松控制通常需要的并发量。 ETC。
// create a queue object with concurrency 2
var q = async.queue(function(task, callback) {
console.log('Hello ' + task.name);
callback();
}, 2);
// assign a callback
q.drain = function() {
console.log('All items have been processed');
};
// add some items to the queue
q.push({name: 'foo'}, function(err) {
console.log('Finished processing foo');
});
q.push({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});
// add some items to the queue (batch-wise)
q.push([{name: 'baz'},{name: 'bay'},{name: 'bax'}], function(err) {
console.log('Finished processing item');
});
// add some items to the front of the queue
q.unshift({name: 'bar'}, function (err) {
console.log('Finished processing bar');
});
Run Code Online (Sandbox Code Playgroud)
致谢 Medium 文章作者(阅读更多)
小智 7
您可以调用多个异步函数而无需等待它们。这将并行执行它们。这样做时,将返回的 Promise 保存在变量中,并在某个时刻单独等待它们或使用 Promise.all() 并处理结果。
您还可以使用 try...catch 包装函数调用,以处理单个异步操作的失败并提供回退逻辑。
下面是一个示例:观察日志,在各个异步函数执行开始时打印的日志会立即打印,即使第一个函数需要 5 秒才能解析。
function someLongFunc () {
return new Promise((resolve, reject)=> {
console.log('Executing function 1')
setTimeout(resolve, 5000)
})
}
function anotherLongFunc () {
return new Promise((resolve, reject)=> {
console.log('Executing function 2')
setTimeout(resolve, 5000)
})
}
async function main () {
let someLongFuncPromise, anotherLongFuncPromise
const start = Date.now()
try {
someLongFuncPromise = someLongFunc()
}
catch (ex) {
console.error('something went wrong during func 1')
}
try {
anotherLongFuncPromise = anotherLongFunc()
}
catch (ex) {
console.error('something went wrong during func 2')
}
await someLongFuncPromise
await anotherLongFuncPromise
const totalTime = Date.now() - start
console.log('Execution completed in ', totalTime)
}
main()Run Code Online (Sandbox Code Playgroud)
function wait(ms, data) {
console.log('Starting task:', data, ms);
return new Promise( resolve => setTimeout(resolve, ms, data) );
}
(async function parallel() {
// step 1 - initiate all promises
console.log('STARTING')
let task1 = wait(2000, 'parallelTask1') // PS: see Exception handling below
let task2 = wait(500, 'parallelTask2')
let task3 = wait(1000, 'parallelTask3')
// step 2 - await all promises
console.log('WAITING')
task1 = await task1
task2 = await task2
task3 = await task3
// step 3 - all results are 100% ready
console.log('FINISHED')
console.log('Result:', task1, task2, task3)
})()Run Code Online (Sandbox Code Playgroud)
await调用完成了代码执行。[task1, task2, task3] = [await task1, await task2, await task3]
Run Code Online (Sandbox Code Playgroud)
let five = getAsyncFive()
let ten = getAsyncTen()
let result = await five * await ten
Run Code Online (Sandbox Code Playgroud)
*请注意,这与let result = await getAsyncFive() * await getAsyncTen()将不会并行运行异步任务不同!
在下面的代码段中,.catch(e => e)捕获到错误并允许链继续运行,从而使诺言得以解决,而不是拒绝。没有catch,代码将引发未处理的异常,并且函数将提前退出。
[task1, task2, task3] = [await task1, await task2, await task3]
Run Code Online (Sandbox Code Playgroud)
第二个代码段未处理,功能将失败。
您也可以打开Devtools并在控制台输出中查看错误。
let five = getAsyncFive()
let ten = getAsyncTen()
let result = await five * await ten
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
140028 次 |
| 最近记录: |