基本的异步/等待模式?

时间:2018-09-12 00:34:14

标签: dart

我正在尝试找出Dart中的异步/等待问题。我正在调用一小段http提取指令,并希望等待所有指令。我创建了此示例代码来演示该问题。

我希望看到“开始测试”,然后依次开始每个下载。然后,每个下载将以随机顺序完成,然后我将看到“最终测试”。但是我什至在开始下载之前就已经看到了“结束测试”。

请帮助我了解我在做错什么。

force_bytes(the_code.split("'")[1])

这是输出。

import 'dart:async';
import 'package:http/http.dart' as http;

class AsyncTest {
  final _resourceList = [
    {
      'name': 'Test 1',
      'url': 'https://jsonplaceholder.typicode.com/posts'
    },
    {
      'name': 'Test 2',
      'url': 'https://jsonplaceholder.typicode.com/comments'
    },
    {
      'name': 'Test 3',
      'url': 'https://jsonplaceholder.typicode.com/albums'
    },
    {
      'name': 'Test 4',
      'url': 'https://jsonplaceholder.typicode.com/photos'
    },
    {
      'name': 'Test 5',
      'url': 'https://jsonplaceholder.typicode.com/users'
    },
  ];

  void beginTest() async {
    print('begin test');
    await getAll();
    print('end test');
  }

  Future<void> getAll() async {
    _resourceList.forEach((resource) async {
      print('begin ${resource['name']}');

      final response = await http.get(resource['url']);

      print('end ${resource['name']}');
    });
  }
}

3 个答案:

答案 0 :(得分:0)

您在await内部进行的getAll()调用允许事件循环处理不同的路径。所以是的,所有早期事物(开始...)首先出现,而后来事物(结束...)以明显随机的顺序出现是有意义的。这是异步编程的固有特性。

答案 1 :(得分:0)

  

我希望每次下载后都能看到“开始测试”   按顺序开始。然后,每个下载将随机完成   命令,然后我会看到“最终测试”。但是我看到“最终测试”   甚至还没有开始下载。

那是因为(偶然)您要求异步调用在之后 Future<void> getAll() async { _resourceList.forEach((resource) async { print('begin ${resource['name']}'); final response = await http.get(resource['url']); print('end ${resource['name']}'); }); }

getAll() function

具体来说,您的功能是:

  1. 输入_resourceList.forEach(...)
  2. 调用getAll()
  3. 进入微任务循环
  4. 令人兴奋的async { ... }功能
  5. 在下一个微任务中,执行for ...回调的主体

您有一些选择。如果您想使用回调,则可以使用Future.waitFuture.forEach,否则getAll()将在退出Future<void> getAll() async { for (var resource in _resourceList) { print('begin ${resource['name']}'); final response = await http.get(resource['url']); print('end ${resource['name']}'); } } -内置{{3 }}。

import React, {Component} from 'react';
import {View, TextInput, TouchableOpacity, Text} from 'react-native';
import {connect} from 'react-redux';
import actions from '../Redux/Action';

class tes extends Component{

    constructor(props){
        super(props)
    }
    render(){
        return(
            <View>
                <TextInput placeholder="phone number"
                    keyboardType="number-pad"/>

                <TouchableOpacity onPress={this.props.onLogin}>
                    <Text>login</Text>
                </TouchableOpacity>
            </View>
        )
    }
}

mapStateToProps = state => {
    return {
        number: state.phoneNumber
    }
}

mapDispatchToProps = dispatch => {
    return {
        onLogin: (number) => {
            dispatch(actions.setLoginNumber(number))
        }
    }
}

export default connect(mapStateToProps, mapDispatchToProps)(tes);

答案 2 :(得分:0)

forEach(callback)忽略了callback的返回值。

如果您使用for循环,则await会按预期工作:

  Future<void> getAll() async {
    for(var resource in _resourceList) {
      print('begin ${resource['name']}');

      final response = await http.get(resource['url']);

      print('end ${resource['name']}');
    }
  }

或者让循环体同时执行,您可以使用

  Future<void> getAll() async {
    return Future.wait(_resourceList.map((resource) async {
      print('begin ${resource['name']}');

      final response = await http.get(resource['url']);

      print('end ${resource['name']}');
    }));
  }

使用map收集从回调返回的Future,当它们全部完成(成功或错误)时,返回的Future将完成。