NoN*_*ded 55 javascript async-await
最后async/ await将在IE以外的所有主流浏览器中得到支持.所以现在我们可以用async/ 开始编写更易读的代码了.await但是有一个问题.很多人使用异步等待这样:
const userResponse = await fetchUserAsync();
const postsResponse = await fetchPostsAsync();
Run Code Online (Sandbox Code Playgroud)
虽然这个代码是可读的,但它有一个问题,它会串行运行这些函数,在完成用户的提取之前它不会开始提取帖子.解决方案很简单,我们需要并行获取资源.
所以我想做的是(伪语言):
fn task() {
result-1 = doAsync();
result-2 = doAsync();
result-n = doLongAsync();
// handle results together
combinedResult = handleResults(result-1, result-2);
lastResult = handleLastResult(result-n);
}
Run Code Online (Sandbox Code Playgroud)
NoN*_*ded 106
你可以写这样的东西:
const responses = await Promise.all([
fetchUserAsync(),
fetchPostsAsync(),
]);
const userResponse = responses[0];
const postsResponse = responses[1];
Run Code Online (Sandbox Code Playgroud)
这很容易吗?但是有一个问题!Promise.all具有快速失败的行为,这意味着,一旦承诺被拒绝,它就会拒绝.可能你想要一个更强大的解决方案,我们负责处理任何提取的拒绝.幸运的是有一个解决方案,它可以简单地使用async/ await不需要使用Promise.all.一个工作的例子:
console.clear();
function wait(ms, data) {
return new Promise( resolve => setTimeout(resolve.bind(this, data), ms) );
}
/**
* This will run in series, because
* we call a function and immediately wait for it's result,
* so this will finish in 1s.
*/
async function series() {
return {
result1: await wait(500, 'seriesTask1'),
result2: await wait(500, 'seriesTask2'),
}
}
/**
* While here we call the functions first,
* then wait for the result later, so
* this will finish in 500ms.
*/
async function parallel() {
const task1 = wait(500, 'parallelTask1');
const task2 = wait(500, 'parallelTask2');
return {
result1: await task1,
result2: await task2,
}
}
async function taskRunner(fn, label) {
const startTime = performance.now();
console.log(`Task ${label} starting...`);
let result = await fn();
console.log(`Task ${label} finished in ${ Number.parseInt(performance.now() - startTime) } miliseconds with,`, result);
}
void taskRunner(series, 'series');
void taskRunner(parallel, 'parallel');
/*
* The result will be:
* Task series starting...
* Task parallel starting...
* Task parallel finished in 500 milliseconds with, { "result1": "parallelTask1", "result2": "parallelTask2" }
* Task series finished in 1001 milliseconds with, { "result1": "seriesTask1", "result2": "seriesTask2" }
*/Run Code Online (Sandbox Code Playgroud)
注意:您需要一个具有async/ 已await 启用以运行此代码段(或nodejs v7及更高版本)的浏览器
这样,您可以简单地使用try/ catch来处理错误,并在parallel函数内返回部分结果.
ric*_*cka 18
如果你对Promise.all的失败快速行为和解构赋值语法没问题:
const [userResponse, postsResponse] = await Promise.all([
fetchUserAsync(),
fetchPostsAsync(),
]);
Run Code Online (Sandbox Code Playgroud)
对于那些询问如何将其扩展到运行时确定的调用次数的人,您可以使用 2 个循环。第一个启动所有任务,第二个等待一切完成
console.clear();
function wait(ms, data) {
return new Promise( resolve => setTimeout(resolve.bind(this, data), ms) );
}
/**
* While here we call the functions first,
* then wait for the result later, so
* this will finish in 500ms.
*/
async function runTasks(timings) {
let tasks = [];
for (let i in timings) {
tasks.push(wait(timings[i], `Result of task ${i}`));
}
/* Want fast fail? use Promise.All */
//return Promise.All(tasks);
let results = [];
for (let task of tasks) {
results.push(await task);
}
return results;
}
async function taskRunner(fn, arg, label) {
const startTime = performance.now();
console.log(`Task ${label} starting...`);
let result = await fn(arg);
console.log(`Task ${label} finished in ${ Number.parseInt(performance.now() - startTime) } miliseconds with,`, result);
}
void taskRunner(runTasks, [50,100,200,60,500], 'Task List');Run Code Online (Sandbox Code Playgroud)