Javascript 如何同步一系列承诺?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29880715/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to synchronize a sequence of promises?
提问by vitaly-t
I have an array of promise objects that must be resolved in the same sequence in which they are listed in the array, i.e. we cannot attempt resolving an element till the previous one has been resolved (as method Promise.all([...])does).
我有一个 promise 对象数组,必须按照它们在数组中列出的相同顺序进行解析,即我们不能尝试解析一个元素,直到前一个元素被解析(就像方法Promise.all([...])一样)。
And if one element is rejected, I need the chain to reject at once, without attempting to resolve the following element.
如果一个元素被拒绝,我需要链立即拒绝,而不尝试解决以下元素。
How can I implement this, or is there an existing implementation for such sequencepattern?
我该如何实现这一点,或者是否有这种sequence模式的现有实现?
function sequence(arr) {
return new Promise(function (resolve, reject) {
// try resolving all elements in 'arr',
// but strictly one after another;
});
}
EDIT
编辑
The initial answers suggest we can only sequenceresults of such array elements, not their execution, because it is predefined in such example.
最初的答案表明我们只能sequence得到这样的数组元素的结果,而不是它们的执行,因为它是在这样的例子中预定义的。
But then how to generate an array of promises in such a way as to avoid early execution?
但是,如何以这种方式生成一系列 Promise 以避免过早执行呢?
Here's a modified example:
这是一个修改后的示例:
function sequence(nextPromise) {
// while nextPromise() creates and returns another promise,
// continue resolving it;
}
I wouldn't want to make it into a separate question, because I believe it is part of the same problem.
我不想把它变成一个单独的问题,因为我相信它是同一个问题的一部分。
SOLUTION
解决方案
Some answers below and discussions that followed went a bit astray, but the eventual solution that did exactly what I was looking for was implemented within spexlibrary, as method sequence. The method can iterate through a sequence of dynamic length, and create promises as required by the business logic of your application.
下面的一些答案和随后的讨论有点误入歧途,但最终的解决方案正是我所寻找的,是在spex库中实现的,作为方法序列。该方法可以遍历动态长度的序列,并根据应用程序的业务逻辑的需要创建承诺。
Later on I turned it into a shared library for everyone to use.
后来我把它变成了一个共享库供大家使用。
回答by jfriend00
Here are some simple examples for how you sequence through an array executing each async operation serially (one after the other).
下面是一些简单的示例,说明如何按顺序(一个接一个)执行每个异步操作的数组。
Let's suppose you have an array of items:
假设您有一组项目:
var arr = [...];
And, you want to carry out a specific async operation on each item in the array, one at a time serially such that the next operation does not start until the previous one has finished.
并且,您希望对数组中的每一项执行特定的异步操作,一次一个,以便下一个操作在前一个操作完成之前不会开始。
And, let's suppose you have a promise returning function for processing one of the items in the array fn(item):
并且,假设您有一个用于处理数组中的一项的承诺返回函数fn(item):
Manual Iteration
手动迭代
function processItem(item) {
// do async operation and process the result
// return a promise
}
Then, you can do something like this:
然后,您可以执行以下操作:
function processArray(array, fn) {
var index = 0;
function next() {
if (index < array.length) {
fn(array[index++]).then(next);
}
}
next();
}
processArray(arr, processItem);
Manual Iteration Returning Promise
手动迭代返回承诺
If you wanted a promise returned from processArray()so you'd know when it was done, you could add this to it:
如果你想要返回一个 promiseprocessArray()以便你知道它何时完成,你可以将它添加到它:
function processArray(array, fn) {
var index = 0;
function next() {
if (index < array.length) {
return fn(array[index++]).then(function(value) {
// apply some logic to value
// you have three options here:
// 1) Call next() to continue processing the result of the array
// 2) throw err to stop processing and result in a rejected promise being returned
// 3) return value to stop processing and result in a resolved promise being returned
return next();
});
}
} else {
// return whatever you want to return when all processing is done
// this returne value will be the ersolved value of the returned promise.
return "all done";
}
}
processArray(arr, processItem).then(function(result) {
// all done here
console.log(result);
}, function(err) {
// rejection happened
console.log(err);
});
Note: this will stop the chain on the first rejection and pass that reason back to the processArray returned promise.
注意:这将在第一次拒绝时停止链并将该原因传递回 processArray 返回的承诺。
Iteration with .reduce()
使用 .reduce() 进行迭代
If you wanted to do more of the work with promises, you could chain all the promises:
如果你想用 Promise 做更多的工作,你可以链接所有的 Promise:
function processArray(array, fn) {
return array.reduce(function(p, item) {
return p.then(function() {
return fn(item);
});
}, Promise.resolve());
}
processArray(arr, processItem).then(function(result) {
// all done here
}, function(reason) {
// rejection happened
});
Note: this will stop the chain on the first rejection and pass that reason back to the promise returned from processArray().
注意:这将在第一次拒绝时停止链并将该原因传递回从 返回的承诺processArray()。
For a success scenario, the promise returned from processArray()will be resolved with the last resolved value of your fncallback. If you wanted to accumulate a list of results and resolve with that, you could collect the results in a closure array from fnand continue to return that array each time so the final resolve would be an array of results.
对于成功场景,返回的承诺processArray()将使用fn回调的最后一个已解析值进行解析。如果你想累积一个结果列表并用它来解决,你可以从一个闭包数组中收集结果,fn然后每次继续返回该数组,这样最终的解决方案就是一个结果数组。
Iteration with .reduce() that Resolves With Array
用 .reduce() 迭代,用数组解决
And, since it now seems apparent that you want the final promise result to be an array of data (in order), here's a revision of the previous solution that produces that:
而且,由于现在似乎您希望最终的承诺结果是一个数据数组(按顺序),这里是对先前解决方案的修订,该解决方案产生了:
function processArray(array, fn) {
var results = [];
return array.reduce(function(p, item) {
return p.then(function() {
return fn(item).then(function(data) {
results.push(data);
return results;
});
});
}, Promise.resolve());
}
processArray(arr, processItem).then(function(result) {
// all done here
// array of data here in result
}, function(reason) {
// rejection happened
});
Working demo: http://jsfiddle.net/jfriend00/h3zaw8u8/
工作演示:http: //jsfiddle.net/jfriend00/h3zaw8u8/
And a working demo that shows a rejection: http://jsfiddle.net/jfriend00/p0ffbpoc/
以及显示拒绝的工作演示:http: //jsfiddle.net/jfriend00/p0ffbpoc/
Iteration with .reduce() that Resolves With Array with delay
使用 .reduce() 进行迭代,使用延迟解析数组
And, if you want to insert a small delay between operations:
而且,如果您想在操作之间插入一个小的延迟:
function delay(t, v) {
return new Promise(function(resolve) {
setTimeout(resolve.bind(null, v), t);
});
}
function processArrayWithDelay(array, t, fn) {
var results = [];
return array.reduce(function(p, item) {
return p.then(function() {
return fn(item).then(function(data) {
results.push(data);
return delay(t, results);
});
});
}, Promise.resolve());
}
processArray(arr, 200, processItem).then(function(result) {
// all done here
// array of data here in result
}, function(reason) {
// rejection happened
});
Iteration with Bluebird Promise Library
使用 Bluebird Promise 库进行迭代
The Bluebird promise library has a lot of concurrency controlling features built right in. For example, to sequence iteration through an array, you can use Promise.mapSeries().
Bluebird promise 库内置了许多并发控制功能。例如,要对数组进行排序迭代,您可以使用Promise.mapSeries().
Promise.mapSeries(arr, function(item) {
// process each individual item here, return a promise
return processItem(item);
}).then(function(results) {
// process final results here
}).catch(function(err) {
// process array here
});
Or to insert a delay between iterations:
或者在迭代之间插入延迟:
Promise.mapSeries(arr, function(item) {
// process each individual item here, return a promise
return processItem(item).delay(100);
}).then(function(results) {
// process final results here
}).catch(function(err) {
// process array here
});
Using ES7 async/await
使用 ES7 异步/等待
If you're coding in an environment that supports async/await, you can also just use a regular forloop and then awaita promise in the loop and it will cause the forloop to pause until a promise is resolved before proceeding. This will effectively sequence your async operations so the next one doesn't start until the previous one is done.
如果您在支持 async/await 的环境中编码,您也可以只使用一个常规for循环,然后await在循环中使用一个承诺,这将导致for循环暂停,直到在继续之前解决一个承诺。这将有效地对您的异步操作进行排序,因此在前一个操作完成之前,下一个操作不会开始。
async function processArray(array, fn) {
let results = [];
for (let i = 0; i < array.length; i++) {
let r = await fn(array[i]);
results.push(r);
}
return results; // will be resolved value of promise
}
// sample usage
processArray(arr, processItem).then(function(result) {
// all done here
// array of data here in result
}, function(reason) {
// rejection happened
});
FYI, I think my processArray()function here is very similar to Promise.map()in the Bluebird promise library which takes an array and a promise producing function and returns a promise that resolves with an array of resolved results.
仅供参考,我认为我processArray()在这里的函数与Promise.map()Bluebird promise 库中的函数非常相似,它接受一个数组和一个 promise 生成函数,并返回一个使用已解析结果数组进行解析的 promise。
@vitaly-t - Here some some more detailed comments on your approach. You are welcome to whatever code seems best to you. When I first started using promises, I tended to use promises only for the simplest things they did and write a lot of the logic myself when a more advanced use of promises could do much more of it for me. You use only what you are fully comfortable with and beyond that, you'd rather see your own code that you intimately know. That's probably human nature.
@vitaly-t - 这里有一些关于你的方法的更详细的评论。欢迎您使用任何您认为最好的代码。当我第一次开始使用 Promise 时,我倾向于仅将 Promise 用于他们所做的最简单的事情,并且当更高级的 Promise 使用可以为我做更多的事情时,我自己编写了很多逻辑。你只使用你完全熟悉的东西,除此之外,你更愿意看到你自己熟悉的代码。这大概就是人性吧。
I will suggest that as I understood more and more of what promises can do for me, I now like to write code that uses more of the advanced features of promises and it seems perfectly natural to me and I feel like I'm building on well tested infrastructure that has lots of useful features. I'd only ask that you keep your mind open as you learn more and more to potentially go that direction. It's my opinion that it's a useful and productive direction to migrate as your understanding improves.
我会建议,随着我对 Promise 可以为我做什么的了解越来越多,我现在喜欢编写使用更多 Promise 高级功能的代码,这对我来说似乎很自然,我觉得我正在建立良好的基础经过测试的基础设施具有许多有用的功能。我只是要求你在学习越来越多的知识时保持开放的心态,以便朝着那个方向前进。我认为,随着您的理解提高,迁移是一个有用且富有成效的方向。
Here are some specific points of feedback on your approach:
以下是对您的方法的一些具体反馈意见:
You create promises in seven places
你在七个地方创建承诺
As a contrast in styles, my code has only twoplaces where I explicitly create a new promise - once in the factory function and once to initialize the .reduce()loop. Everywhere else, I'm just building on the promises already created by chaining to them or returning values within them or just returning them directly. Your code has sevenunique places where you're creating a promise. Now, good coding isn't a contest to see how few places you can create a promise, but that might point out the difference in leverage the promises that are already created versus testing conditions and creating new promises.
作为风格的对比,我的代码只有两个地方我显式地创建了一个新的承诺 - 一次在工厂函数中,一次用于初始化.reduce()循环。在其他地方,我只是通过链接到它们或返回其中的值或直接返回它们来构建已经创建的承诺。您的代码有七个独特的地方,您可以在其中创建承诺。现在,好的编码不是看可以创建承诺的地方有多少的竞赛,但这可能会指出利用已经创建的承诺与测试条件和创建新承诺的差异。
Throw-safety is a very useful feature
投掷安全是一个非常有用的功能
Promises are throw-safe. That means that an exception thrown within a promise handler will automatically reject that promise. If you just want the exception to become a rejection, then this is a very useful feature to take advantage of. In fact, you will find that just throwing yourself is a useful way to reject from within a handler without creating yet another promise.
Promise 是抛出安全的。这意味着承诺处理程序中抛出的异常将自动拒绝该承诺。如果你只是想让异常变成拒绝,那么这是一个非常有用的特性。事实上,你会发现直接抛出自己是一种从处理程序中拒绝而不创建另一个承诺的有用方法。
Lots of Promise.resolve()or Promise.reject()is probably an opportunity for simplification
很多Promise.resolve()或Promise.reject()可能是简化的机会
If you see code with lots of Promise.resolve()or Promise.reject()statements, then there are probably opportunities to leverage the existing promises better rather than creating all these new promises.
如果您看到包含大量Promise.resolve()orPromise.reject()语句的代码,那么可能有机会更好地利用现有的 Promise,而不是创建所有这些新的 Promise。
Cast to a Promise
投向承诺
If you don't know if something returned a promise, then you can cast it to a promise. The promise library will then do it's own checks whether it is a promise or not and even whether it's the kind of promise that matches the promise library you're using and, if not, wrap it into one. This can save rewriting a lot of this logic yourself.
如果您不知道某些东西是否返回了承诺,那么您可以将其转换为承诺。然后,promise 库会自己检查它是否是一个promise,甚至它是否与您正在使用的promise 库相匹配,如果不是,则将其包装成一个。这样可以省去自己重写很多这样的逻辑。
Contract to Return a Promise
返回承诺的合同
In many cases these days, it's completely viable to have a contract for a function that may do something asynchronous to return a promise. If the function just wants to do something synchronous, then it can just return a resolved promise. You seem to feel like this is onerous, but it's definitely the way the wind is blowing and I already write lots of code that requires that and it feels very natural once you get familiar with promises. It abstracts away whether the operation is sync or async and the caller doesn't have to know or do anything special either way. This is a nice use of promises.
在如今的许多情况下,为可能执行异步操作以返回承诺的函数签订合同是完全可行的。如果函数只是想做一些同步的事情,那么它可以只返回一个已解决的承诺。你似乎觉得这很繁重,但这绝对是风吹草动的方式,我已经写了很多需要这样做的代码,一旦你熟悉了 promises 就会感觉很自然。它抽象出操作是同步还是异步,并且调用者不必知道或以任何方式做任何特殊的事情。这是 Promise 的一个很好的用法。
The factory function can be written to create one promise only
可以编写工厂函数来仅创建一个承诺
The factory function can be written to create one promise only and then resolve or reject it. This style also makes it throw safe so any exception occuring in the factory function automatically becomes a reject. It also makes the contract to always return a promise automatic.
可以编写工厂函数来仅创建一个承诺,然后解决或拒绝它。这种风格还使其安全抛出,因此工厂函数中发生的任何异常都会自动变为拒绝。它还使合同始终自动返回承诺。
While I realize this factory function is a placeholder function (it doesn't even do anything async), hopefully you can see the style to consider it:
虽然我意识到这个工厂函数是一个占位符函数(它甚至不做任何异步操作),但希望你能看到考虑它的风格:
function factory(idx) {
// create the promise this way gives you automatic throw-safety
return new Promise(function(resolve, reject) {
switch (idx) {
case 0:
resolve("one");
break;
case 1:
resolve("two");
break;
case 2:
resolve("three");
break;
default:
resolve(null);
break;
}
});
}
If any of these operations were async, then they could just return their own promises which would automatically chain to the one central promise like this:
如果这些操作中的任何一个是异步的,那么他们可以只返回自己的承诺,这些承诺会自动链接到一个中央承诺,如下所示:
function factory(idx) {
// create the promise this way gives you automatic throw-safety
return new Promise(function(resolve, reject) {
switch (idx) {
case 0:
resolve($.ajax(...));
case 1:
resole($.ajax(...));
case 2:
resolve("two");
break;
default:
resolve(null);
break;
}
});
}
Using a reject handler to just return promise.reject(reason)is not needed
return promise.reject(reason)不需要使用拒绝处理程序
When you have this body of code:
当你有这段代码时:
return obj.then(function (data) {
result.push(data);
return loop(++idx, result);
}, function (reason) {
return promise.reject(reason);
});
The reject handler is not adding any value. You can instead just do this:
拒绝处理程序没有添加任何值。您可以改为这样做:
return obj.then(function (data) {
result.push(data);
return loop(++idx, result);
});
You are already returning the result of obj.then(). If either objrejects or if anything chained to objor returned from then .then()handler rejects, then objwill reject. So you don't need to create a new promise with the reject. The simpler code without the reject handler does the same thing with less code.
您已经在返回 的结果obj.then()。如果obj拒绝,或者如果任何链接到objthen.then()处理程序或从 then 返回的任何内容拒绝,obj则将拒绝。所以你不需要用拒绝创建一个新的承诺。没有拒绝处理程序的更简单的代码用更少的代码做同样的事情。
Here's a version in the general architecture of your code that tries to incorporate most of these ideas:
这是您的代码的一般架构中的一个版本,它试图结合大多数这些想法:
function factory(idx) {
// create the promise this way gives you automatic throw-safety
return new Promise(function(resolve, reject) {
switch (idx) {
case 0:
resolve("zero");
break;
case 1:
resolve("one");
break;
case 2:
resolve("two");
break;
default:
// stop further processing
resolve(null);
break;
}
});
}
// Sequentially resolves dynamic promises returned by a factory;
function sequence(factory) {
function loop(idx, result) {
return Promise.resolve(factory(idx)).then(function(val) {
// if resolved value is not null, then store result and keep going
if (val !== null) {
result.push(val);
// return promise from next call to loop() which will automatically chain
return loop(++idx, result);
} else {
// if we got null, then we're done so return results
return result;
}
});
}
return loop(0, []);
}
sequence(factory).then(function(results) {
log("results: ", results);
}, function(reason) {
log("rejected: ", reason);
});
Working demo: http://jsfiddle.net/jfriend00/h3zaw8u8/
工作演示:http: //jsfiddle.net/jfriend00/h3zaw8u8/
Some comments about this implementation:
关于这个实现的一些评论:
Promise.resolve(factory(idx))essentially casts the result offactory(idx)to a promise. If it was just a value, then it becomes a resolved promise with that return value as the resolve value. If it was already a promise, then it just chains to that promise. So, it replaces all your type checking code on the return value of thefactory()function.The factory function signals that it is done by returning either
nullor a promise who's resolved value ends up beingnull. The above cast maps those two conditions to the same resulting code.The factory function catches exceptions automatically and turns them into rejects which are then handled automatically by the
sequence()function. This is one significant advantage of letting promises do a lot of your error handling if you just want to abort processing and feed the error back on the first exception or rejection.The factory function in this implementation can return either a promise or a static value (for a synchronous operation) and it will work just fine (per your design request).
I've tested it with a thrown exception in the promise callback in the factory function and it does indeed just reject and propagate that exception back to reject the sequence promise with the exception as the reason.
This uses a similar method as you (on purpose, trying to stay with your general architecture) for chaining multiple calls to
loop().
Promise.resolve(factory(idx))基本上将结果factory(idx)转换为承诺。如果它只是一个值,那么它就变成了一个以返回值作为解析值的已解析承诺。如果它已经是一个承诺,那么它只是链接到那个承诺。因此,它替换了factory()函数返回值上的所有类型检查代码。工厂函数表示它是通过返回一个
null或一个已解决的值最终为 的承诺来完成的null。上面的转换将这两个条件映射到相同的结果代码。工厂函数自动捕获异常并将它们转换为拒绝,然后由
sequence()函数自动处理。如果您只想中止处理并将错误反馈给第一个异常或拒绝,那么这是让 Promise 进行大量错误处理的一个显着优势。此实现中的工厂函数可以返回承诺或静态值(对于同步操作),并且它会正常工作(根据您的设计要求)。
我已经在工厂函数的承诺回调中使用抛出的异常对其进行了测试,它确实只是拒绝并将该异常传播回以拒绝以异常为原因的序列承诺。
这使用与您类似的方法(有意尝试保持您的一般架构)将多个调用链接到
loop().
回答by Benjamin Gruenbaum
Promises represent valuesof operations and not the operations themselves. The operations are already startedso you can't make them wait for one another.
Promise 代表操作的值,而不是操作本身。操作已经开始,所以你不能让他们互相等待。
Instead, you can synchronize functions that return promisesinvoking them in order (through a loop with promise chaining for instance), or using the .eachmethod in bluebird.
相反,您可以同步返回按顺序调用它们的承诺的函数(例如,通过带有承诺链接的循环),或使用.eachbluebird 中的方法。
回答by Amir Popovich
You can't simply run X async operations and then want them to be resolved in an order.
您不能简单地运行 X 异步操作,然后希望它们按顺序解决。
The correct way to do something like this is to run the new async operation only after the one before was resolved:
执行此类操作的正确方法是仅在解决之前的异步操作后运行新的异步操作:
doSomethingAsync().then(function(){
doSomethingAsync2().then(function(){
doSomethingAsync3();
.......
});
});
Edit
Seems like you want to wait for all promises and then invoke their callbacks in a specific order. Something like this:
编辑
似乎您想等待所有承诺,然后按特定顺序调用它们的回调。像这样的东西:
var callbackArr = [];
var promiseArr = [];
promiseArr.push(doSomethingAsync());
callbackArr.push(doSomethingAsyncCallback);
promiseArr.push(doSomethingAsync1());
callbackArr.push(doSomethingAsync1Callback);
.........
promiseArr.push(doSomethingAsyncN());
callbackArr.push(doSomethingAsyncNCallback);
and then:
进而:
$.when(promiseArr).done(function(promise){
while(callbackArr.length > 0)
{
callbackArr.pop()(promise);
}
});
The problems that can occur with this is when one or more promises fail.
当一个或多个承诺失败时,可能会出现问题。
回答by Molomby
Although quite dense, here's another solution that will iterate a promise-returning function over an array of values and resolve with an array of results:
尽管非常密集,但这里有另一种解决方案,它将在一组值上迭代一个返回承诺的函数并使用一组结果进行解析:
function processArray(arr, fn) {
return arr.reduce(
(p, v) => p.then((a) => fn(v).then(r => a.concat([r]))),
Promise.resolve([])
);
}
Usage:
用法:
const numbers = [0, 4, 20, 100];
const multiplyBy3 = (x) => new Promise(res => res(x * 3));
// Prints [ 0, 12, 60, 300 ]
processArray(numbers, multiplyBy3).then(console.log);
Note that, because we're reducing from one promise to the next, each item is processed in series.
请注意,因为我们从一个 promise 减少到下一个 promise,所以每个项目都是按顺序处理的。
It's functionally equivalent to the "Iteration with .reduce() that Resolves With Array" solution from @jfriend00 but a bit neater.
它在功能上等同于来自@jfriend00 的“使用 .reduce() 进行迭代解决数组”解决方案,但更简洁一些。
回答by Brady Edgar
In my opinion, you should be using a for loop(yes the only time I would recommend a for loop). The reason is that when you are using a for loop it allows you to awaiton each of the iterations of your loop where using reduce, mapor forEachwith run all your promise iterations concurrently. Which by the sounds of it is not what you want, you want each promise to wait until the previous promise has resolved. So to do this you would do something like the following.
在我看来,您应该使用 for 循环(是的,这是我唯一推荐使用 for 循环的时候)。原因是当您使用 for 循环时,它允许您await在循环的每个迭代中使用reduce,map或forEach同时运行所有承诺迭代。这听起来不是你想要的,你希望每个承诺都等到前一个承诺解决。因此,要做到这一点,您将执行以下操作。
const ids = [0, 1, 2]
const accounts = ids.map(id => getId(id))
const accountData = async() => {
for await (const account of accounts) {
// account will equal the current iteration of the loop
// and each promise are now waiting on the previous promise to resolve!
}
}
// then invoke your function where ever needed
accountData()
And obviously, if you wanted to get really extreme you could do something like this:
显然,如果你想变得非常极端,你可以这样做:
const accountData = async(accounts) => {
for await (const account of accounts) {
// do something
}
}
accountData([0, 1, 2].map(id => getId(id)))
This is so much more readable than any of the other examples, it is much less code, reduced the number of lines needed for this functionality, follows a more functional programming way of doing things and is using ES7 to its full potential!!!!
这比任何其他示例都更具可读性,它的代码少得多,减少了此功能所需的行数,遵循更具功能性的编程方式,并充分利用 ES7 的潜力!!!!
Also depending on your set up or when you are reading this you may need to add the plugin-proposal-async-generator-functionspolyfill or you may see the following error
此外,根据您的设置或阅读本文时,您可能需要添加plugin-proposal-async-generator-functionspolyfill,否则您可能会看到以下错误
@babel/plugin-proposal-async-generator-functions (https://git.io/vb4yp) to the 'plugins' section of your Babel config to enable transformation.
@babel/plugin-proposal-async-generator-functions (https://git.io/vb4yp) to the 'plugins' section of your Babel config to enable transformation.
回答by Iman Bahrampour
I suppose two approaches for handling this question:
我想有两种处理这个问题的方法:
- Create multiple promises and use the allWithAsync function as follow:
- 创建多个 Promise 并使用 allWithAsync 函数,如下所示:
let allPromiseAsync = (...PromisesList) => { return new Promise(async resolve => { let output = [] for (let promise of PromisesList) { output.push(await promise.then(async resolvedData => await resolvedData)) if (output.length === PromisesList.length) resolve(output) } }) } const prm1= Promise.resolve('first'); const prm2= new Promise((resolve, reject) => setTimeout(resolve, 2000, 'second')); const prm3= Promise.resolve('third'); allPromiseAsync(prm1, prm2, prm3) .then(resolvedData => { console.log(resolvedData) // ['first', 'second', 'third'] });
let allPromiseAsync = (...PromisesList) => { return new Promise(async resolve => { let output = [] for (let promise of PromisesList) { output.push(await promise.then(async resolvedData => await resolvedData)) if (output.length === PromisesList.length) resolve(output) } }) } const prm1= Promise.resolve('first'); const prm2= new Promise((resolve, reject) => setTimeout(resolve, 2000, 'second')); const prm3= Promise.resolve('third'); allPromiseAsync(prm1, prm2, prm3) .then(resolvedData => { console.log(resolvedData) // ['first', 'second', 'third'] });
- Use the Promise.all function instead:
- 改用 Promise.all 函数:
(async () => { const promise1 = new Promise(resolve => { setTimeout(() => { console.log('first');console.log(new Date());resolve() }, 1000) }) const promise2 = new Promise(resolve => { setTimeout(() => {console.log('second');console.log(new Date()); resolve() }, 3000) }) const promise3 = new Promise(resolve => { setTimeout(() => { console.log('third');console.log(new Date()); resolve() }, 7000) }) const promises = [promise1, promise2, promise3] await Promise.all(promises) console.log('This line is shown after 7000ms') })()
(async () => { const promise1 = new Promise(resolve => { setTimeout(() => { console.log('first');console.log(new Date());resolve() }, 1000) }) const promise2 = new Promise(resolve => { setTimeout(() => {console.log('second');console.log(new Date()); resolve() }, 3000) }) const promise3 = new Promise(resolve => { setTimeout(() => { console.log('third');console.log(new Date()); resolve() }, 7000) }) const promises = [promise1, promise2, promise3] await Promise.all(promises) console.log('This line is shown after 7000ms') })()

