zoukankan      html  css  js  c++  java
  • 异步

    AsyncCallback

    意义:

    异步操作完成时调用的方法

    语法1:

    构造异步回调对象

    AsyncCallback 异步回调对象名asyncCallback = new AsyncCallback(异步操作完成时调用的方法MyAsyncCallback);

    语法2:

    定义委托,并进行异步调用,异步调用完成后自动触发

    委托类型Action fn委托名 = Run委托定义;
    委托名fn.BeginInvoke(异步回调对象名asyncCallback );

    示例:

     
    using System;
    
    namespace Examples.AdvancedProgramming.AsynchronousOperations
    {
        public class UseDelegateForAsyncCallback
        {
            delegate string MethodDelegate(int iCallTime);
            public static void Main()
            {
                MethodDelegate dlgt = (m)=> 
                {
                    return "你输入的数字是"+m;
                };
                AsyncCallback asyncCallback = new AsyncCallback(MyAsyncCallback);           
                Action fn = Run;
                fn.BeginInvoke(asyncCallback,null);
    
            }
    
            private static void MyAsyncCallback(IAsyncResult ar)
            {
                Console.WriteLine("异步调用");
                Console.ReadLine();
            }
    
    
            public static void Run()
            {
    
            }
        }
    }
    ///  控制台输出结果:
    ///     你输入的数字是:5
    ///     异步调用

    JS异步编程

    JS三座大山:原型原型链、作用域闭包、同步异步。
    之前有写过自己对闭包的理解,今天来总结一下JS中的异步。

    思考(案例来自stackoverflow):

    function foo(){
        var result;
        $ajax({
            url:'...',
            success:function(response){
                result=response;
                //return response;//tried this one as well
            }
        });
        return result;
    }
    var result=foo();

    初学异步的时候,这里是很容易错的地方,你想要获取从服务器端返回的数据,结果却一直undefined。
    分析:
    JavaScript是单线程语言,但是js中有很多任务耗时比较长,比如ajax请求,如果都按照顺序进行,往往会出现浏览器无响应的情况,所以就需要异步的形式。JS中所有的任务可以分为两种:同步任务和异步任务。

    同步任务:在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

    异步任务:不进入主线程,而进入任务队列中的任务,只有任务队列通知主线程,某个异步任务可以执行了,这个任务才会进入主线程执行。

    事件循环(Event Loop):只有执行栈中的所有同步任务都执行完毕,系统才会读取任务队列,看看里面的异步任务哪些可以执行,然后那些对应的异步任务,结束等待状态,进入执行栈,开始执行。


    异步的解决方案:

    下面我们尝试将上面代码改正一下,几种方法如下:
    1.callback

    function foo(callback){//定义函数的时候将另一个函数(回调函数)作为参数传入定义的函数中。
        $ajax({
            //...
            success:callback//异步操作执行完毕后,再执行该回调函数,确保回调在异步操作之后执行。
        });
    }
    function myCallback(result){
        //...
    }
    foo(myCallback);

    回调函数本身是我们约定俗成的一种叫法,我们定义它,但是并不会自己去执行它,它最终被其他人执行了。

    优点:比较容易理解;
    缺点:1.高耦合,维护困难,回调地狱;2.每个任务只能指定一个回调函数;3.如果几个异步操作之间并没有顺序之分,同样也要等待上一个操作执行结束再进行下一个操作。下图回调地狱(图片来自于新浪微博(@ruanyf)):

    图片描述

    2.Promise

    function ajax(url){
        return new Promise(function(resolve,reject){
            var xhr=new XMLHttpRequest();
            xhr.onload=function(){
                resolve(this.responseText);
            };
            xhr.onerror=reject;
            xhr.open('GET',url);
            xhr.send();
        });
    }
    ajax('/echo/json')
        .then(function(result){...})
        .then(function(){...})
        .catch(function(){...});

    ES6给我们提供了一个原生的构造函数Promise,Promise代表了一个异步操作,可以将异步对象和回调函数脱离开来,通过.then方法在这个异步操作上绑定回调函数,Promise可以让我们通过链式调用的方法去解决回调嵌套的问题,而且由于promise.all这样的方法存在,可以让同时执行多个操作变得简单。

    promise对象存在三种状态:
    1)Fulfilled:成功状态
    2)Rejected:失败状态
    3)Pending:既不是成功也不是失败状态,可以理解为进行中状态

    promise对象的两个重要方法:resolve/reject
    1)resolve方法可以使Promise对象的状态改变为成功,同时传递一个参数用于后续成功后的操作。
    2)reject方法可以将Promise对象的状态改变为失败,同时将错误信息传递到后续错误处理的操作。

    .then可以使用链式调用,原因在于:每一次执行该方法时总会返回一个Promise对象。
    另外,在then的函数当中的返回值,可以作为后续操作的参数(例如:.then(return a).then(console.log(a+b)))

    那么问题来了,如果上面代码异步操作抛出错误,会怎么样?会调用catch方法指定的回调函数,处理这个错误,而且then方法指定的回调函数,如果运行中抛出错误,也会被catch捕获。Promise对象的错误具有“冒泡”性质,会一直向后传递,直到被捕获为止,也就是说,错误总是会被下一个catch语句捕获。

    理解Promise用法的关键点:
    1.then方法是Promise实例的方法,即Promise.prototype上的,它的作用是为Promise实例添加状态改变时的回调函数,这个方法的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
    2.链式中的第二个then开始,它们的resolve中的参数,是前一个then中resolve的return语句的返回值。
    3.关于执行顺序:Promise在实例化的时候就会执行,也就是如果Promise的实例化语句中函数console.log输出语句,它会比then中的先执行。Promise.all中传入的Promise对象的数组(假设为p1、p2),即使p2的运行速度比p1快,Promise.all方法仍然会按照数组中的顺序将结果返回。
    理解了上面这些方便写原生的Promise,利用观察者模式。后面补充。

    Promise的缺点:
    1.当处于未完成状态时,无法确定目前处于哪一阶段。
    2.如果不设置回调函数,Promise内部的错误不会反映到外部。
    3.无法取消Promise,一旦新建它就会立即执行,无法中途取消。

    3.async/await:

    很多人说async/await是异步编程的终极解决方案、
    JavaScript 的 async/await 实现,离不开 Promise。

    var superagent=require('superagent')
    function delay(){
        return new Promise(function(resolve,reject){
            setTimeout({
                resolve(42);
            },3000);
        })
    }
    async function getAllBooks(){
        var bookIDs=await superagent.get('/user/books');
        await delay(1000);
        return await superagent.get('/books/ids='JSON.stringify(bookIDs));
    }
    getAllBooks()
        .then(function(){});

    上面的 delay() 没有申明为 async。实际上,delay() 本身就是返回的 Promise 对象,加不加 async 结果都一样。

    只要在函数名之前加上async关键字,就表明这个函数内部有异步操作。这个异步操作返回一个Promise对象,前面用await关键字注明。函数执行的时候,一旦遇到await,就会先执行await后面的表达式中的内容(异步),不再执行函数体后面的语句。等到异步操作执行完毕后,再自动返回到函数体内,继续执行函数体后面的语句。

    async:定义异步函数
    1)自动把函数转换为Promise
    2)当调用异步函数时,函数返回值会被resolve处理
    3)异步函数内部可以使用await

    await:暂停异步函数的执行
    1)当使用在Promise前面时,await等待Promise完成,并返回Promise的结果
    2)await只能和Promise一起使用,不能和callback一起使用
    3)await只能用在async函数中

    async/await并不会取代promise,因为async/await底层依然使用promise。

    async function getABC(){
        let A = await getValueA(); // getValueA 花费 2 秒
        let B = await getValueB(); // getValueA 花费 4 秒
        let C = await getValueC(); // getValueA 花费 3 秒
        return A*B*C
    }

    每次遇到 await 关键字时,Promise 都会停下在,一直到运行结束,所以总共花费是 2+4+3 = 9 秒。await 把异步变成了同步。

    async function getABC() {
        // Promise.all() 允许同时执行所有的异步函数
        let results = await Promise.all([ getValueA, getValueB, getValueC ]); 
        return results.reduce((total,value) => total * value);
    }
    

    函数总耗时为 4 秒(getValueB 的耗时)。

    Async 的价值在于用写同步的方式写异步,1避免了阻塞,2必免写回调

    搬运https://www.cnblogs.com/ggmh/p/10054275.html

     

     
  • 相关阅读:
    Redis 笔记
    React Native
    docker run 命令
    vue 集成腾讯地图基础api Demo集合
    在uniapp H5项目中使用腾讯地图sdk
    基于UE4/Unity绘制地图
    腾讯位置服务打车乘客端小车平滑移动-安卓篇
    腾讯位置服务定位打卡功能实现
    腾讯位置服务GPS轨迹回放-安卓篇
    腾讯位置服务个性化图层创建及发布
  • 原文地址:https://www.cnblogs.com/kazama/p/10197577.html
Copyright © 2011-2022 走看看