zoukankan      html  css  js  c++  java
  • AsyncCallback

    AsyncCallback 异步回调委托

    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必免写回调

  • 相关阅读:
    环境是如何建立的 启动文件有什么
    环境中存储的是什么
    串行 并行 异步 同步
    TPC-H is a Decision Support Benchmark
    进程通信类型 管道是Linux支持的最初Unix IPC形式之一 命名管道 匿名管道
    删除环境变量
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.2 autocommit, Commit, and Rollback 自动提交 提交和回滚
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
    14.3.2.1 Transaction Isolation Levels 事务隔离级别
  • 原文地址:https://www.cnblogs.com/ggmh/p/10054275.html
Copyright © 2011-2022 走看看