router.get('/getData', function(req, res) {
var data=[1,2,3];
var result=data.map(function(v, i, a) {
Fee.findOne({
studentid: "57b525bc4e8d464803167da7"
}, {}, function(err, fees) {
if (err) return handleError(err);
var array_test = [];
array_test[i] = {};
array_test[i].number = v;
array_test[i].fees = fees;
console.log('++++++array_test[i]++++++')
console.log(array_test[i])
console.log('++++++array_test[i]++++++')
return array_test[i];
console.log('-----result-----');
console.log(result);
console.log('-----result-----');
res.jsonp({
one: 'aa',
two: 'bb',
three: result
页面发送请求http://127.0.0.1:3000/getdata时,jsonp返回的数据是空,也就是result为空。
结果如图所示:
首先可以肯定,查询结果不为空,因为查询条件是专门设定的。
我们知道Array.forEach .map是同步(阻塞)的,也就是在循环结束后,后面的语句才会被执行,如果按照这个逻辑,jsonp返回的result不会为空,那问题出在哪里?
经过分析,查询结果确实不为空,这个可以从服务器控制台打印结果看出。如图黄色部分即为被赋予查询结果的array_test[i]:
这时候,会发现result打印的位置(红框部分)居然在array_test[i]结果之前,这和代码的顺序不符合呀!它变成了异步执行。
通过查询mongoose文档可以发现,Model.findOne([conditions], [projection], [options], [callback])是一个异步执行的函数,有结果就会调用callback。而node中的map()、forEach()、for()循环有一个特性:当其函数里面里面有回调它就变成异步。map就变成了这样,第一次循环开始,findOne查询数据库,不等有结果就开始第二次查询开始,…第三次查询开始,循环结束,不等有结果它就开始执行console.log(result),所以result为空,而且打印结果在array_test[i]之前。
为了证明分析对不对,我简单测了一下,既然findOne是异步函数,那么如果我在map中不用异步函数,是不是打印顺序和代码书写顺序就是一样的?
代码如下:
router.get('/getData', function(req, res) {
var data = [1, 2, 3];
var result = data.map(function(v, i, a) {
var array_test = [];
array_test[i] = {};
array_test[i].number = v;
array_test[i].fees = 'cc';
return array_test[i];
console.log('-----result-----');
console.log(result);
console.log('-----result-----');
res.jsonp({
one: 'aa',
two: 'bb',
three: result
结果如下:
jsonp返回的result不为空
result的书序也和代码中书写顺序一样
到这里就可以看出,果然是异步的问题导致result为空。那怎么解决?
可以用async的map来处理这种情况,async是nodejs的一个组件,用来解决node的异步问题。而其中的map方法:
对集合中的每一个元素,执行异步操作,得到结果。所有的结果将汇总到最终的callback里。其实就是把异步都加到队列里, 等全都执行完了之后执行一个统一的回调,这样看起来就是同步的效果。
代码如下:
router.get('/getData', function(req, res) {
var data = [1, 2, 3];
var array_test = {};
async.map(data, function(v, callback) {
Fee.findOne({
studentid: "57b525bc4e8d464803167da7"
}, {}, function(err, fees) {
if (err) return handleError(err);
array_test[v]=fees.studentid;
console.log('++++++array_test++++++')
console.log(array_test);
console.log('++++++array_test++++++')
callback(null, array_test);
}, function(err, results) {
console.log('-----result-----');
console.log(results);
console.log('-----result-----');
res.jsonp({
one: 'aa',
two: 'bb',
three: results
页面效果如下图,可以看到result有数据:
服务器控制台效果如下图,可以看到array_test打印在result前面,是同步的顺序:
更多关于async请查看官方文档或者github中文文档。
当然也有其他的方式解决这个问题,比如bluebird、asyncawait,这里不多加分析。
@Test
public void asyncThread()throws Exception{
CompletableFuture async1 = CompletableFuture.runAsync(()->{
try {
Thread.sleep(1000);
System.out.println(Thread.currentThr
问题:解决 forEach 循环无法正确处理异步操作和等待操作的完成
解决方案:1.使用 for...of 循环 2.使用 for 循环 3.使用 Promise.all + map
点击上方“Java基基”,选择“设为星标”做积极的人,而不是积极废人!源码精品专栏原创 | Java 2020超神之路,很肝~中文详细注释的开源项目RPC 框架 Dubbo 源码解析...
// Map.entrySet来遍历key,value, 大容量时推荐使用
map.entrySet().forEach(entry -> {
System.out.println(entry.getKey());
1.实体类中取出某个字段并收集成list
例:传回的是list<实体类>,根据实体类中的id能查询表,这时候普通的就for循环
//x就代表每一个实体类、也是循环中的实体类
// UserList为实体类的集合 List<User>
userList.stream().map(x -> x.getId).collect(Collectors.toList());
上一篇文章,讲述了Future模式的机制、缺点,CompletableFuture产生的由来、静态工厂方法、complete()方法等等。本文将继续整理CompletableFuture的特性。3.3 转换我们可以通过CompletableFuture来异步获取一组数据,并对数据进行一些转换,类似RxJava、Scala的map、flatMap操作。3.3.1 map方法名描述thenApply(...
在JS的 for、foreach、$.each等等的循环体中,本身是不存在阻塞模式的,以下方法本质的原因,是因为匿名函数使用循环体的变量的优先级最高,而普通方式访问的对变量优先级是按代码本身的逻辑顺序的,对变量的访问在循环之后,所以得到的i是循环执行完之后的i,所以不是正确结果;
然而,直接执行匿名函数的方式当场就拿到了正确的i,闭包的方式也是因为将外部函数的变量保存在内存中,从而可以得到正确的...
forEach同/异步问题一、forEach外部等待forEach执行完成二、forEach内部等待异步执行完成三、既需要forEach内部同步执行,又需要forEach外部同步执行
一、forEach外部等待forEach执行完成
let arr = [1, 2, 3, 4, 5, 6, 7];
let arr2 = [];
arr.forEach((item) => {
setTimeout(() => {
arr2.push(item);
}, 1000);
console.log(sum) // 此处输出为0,而不是4,如果这时候后续操作需要用到sum等于4的值,那么就需要修改为如下写法
async getSum() {
const temp = [1,2,3,4,5,6,7,8]
let this.sum =
1.1 正常方式循环 Map
执行结果:1.2 forEach 循环 Map
执行结果:1.3 对于Map 包含的键或值 null ,forEach 将打印 null。
执行结果:1.4 如果不想打印 key=null 的值,可以在 forEach 中指定
执行结果:2.1 正常方式循环列表
执行结果:2.2 Java 8 中,可以使用 forEach 循环一个 List
执行结果:2.3 过滤 List 中的 null 值
执行结果:查看方法签名,它接受一个功能接口 Consumer
这个例子创建了
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("a", "1");
map.put("b", "2");
map.put("c", "3...
js中的map方法内使用异步(调用接口)js中的map方法内使用异步(调用接口)
2019/08/13
js中的map方法内使用异步(调用接口)
map方法里执行的是同步函数,若是想要使用异步,可以使用关键字async await
直接贴代码(我使用的是axios库调用接口)
arr.map( async (item, index) => {//函数使用async关键字