• Javascript异步解决方案总结


    1.回调函数(callback)

    思想:

    通过参数传入回调函数,未来调用回调函数是让函数的条用着判断了发生了什么

    优点:

    容易实现,容易部署

    缺点:

    可读性变差,容易出现回调地狱

    栗子

    function a(cb) {
      console.log("a");
      cb(c);
    }
    a(b);
    function b(cb) {
      console.log("b");
      cb();
    }
    function c() {
      console.log("c");
    }

    我们只写了三个函数可读性就变得极差,出现回调地狱问题

    2.事件的发布订阅

    思想:

    回调函数的事件化,任务执行不取决于代码执行顺序,取决于某个事件是否发生。

    优点:

    容易理解,可以绑定多个事件,每个事件可以指定多个回调函数

    缺点:整个程序变成了事件驱动,运行流程混乱变差

    栗子

    function Events() {
      if (!this instanceof Events) return new Events();
      this.events = {};
    }
    
    Events.prototype.register = function(name, fn) {
      this.events[name] = fn;
    };
    Events.prototype.fire = function(name) {
      events[name]();
    };
    const ins = new Events();
    ins.register("dqhan", function() {});
    ins.fire("dqhan");

    可以随意注册事件,随意执行,虽然灵活但是也导致代码流程混乱,举个场景,组件消息传递,通过父级,如果我们使用了这种事件驱动的方式,是不是就不能直观的看到数据流向问题,如果全都用何种方式实现呢,阅读代码将非常混乱。

    3.延迟函数

    jQuery提出的思想Deferred延迟函数

    思想:

    通过deferred对象对异步操作进行状态绑定,deferred对象统一提供API,对各种异步操作的状态进行操作(成功、失败、进行中)

    优点:避免了层层嵌套的回调函数, deferred对象统一提供接口,是的控制异步操作更加容易

    缺点:状态不可逆,从待定状态切换到另一个状态后,再次调用resolve或者reject对原状态讲不起任何作用。

    特点:外部可以修改deferred的状态

    栗子

    var dtd = $.Deferred();
    var wait = function(dtd) {
      var tasks = function() {
        dtd.resolve();
      };
      setTimeout(tasks, 100);
      return dtd;
    };
    $.when(wait(dtd))
      .done(function() {})
      .fail(function() {});
    
    dtd.resolve(); // 外部随意修改defererd的状态

    4.(继承了Deferred的设计思想)Promise

    ES6提供的异步标准,原生提供了Promise对象

    思想: 一个容器,里面保存着一个异步操作的结果。从语法上来看,Promise是一个对象,提供了统一的API,各种异步操作都可以及使用同样的方法处理

    优点:与deferred一样

    缺点:与deferred一样

    Promise与Deferred的区别

    1.回调API不一样

    2.promise状态不可以在外面随意修改

    promise三种状态:

    pending,resolved,rejected

    promise创建时默认状态为pending状态,当执行了对应的resolve或者reject函数时,修改对应状态

    var promise = new Promise(function(resolve, reject) {
      resolve(value);
      reject(error);
    });

    修改完状态执行相应的api

    var promise = new Promise(function(resolve, reject) {
      resolve(value);
      reject(error);
    })
      .then(res => {
        console.log("resolve");
      })
      .catch(e => {
        console.log("reject");
      });

    promise链式调用

    var promise = new Promise(function(resolve, reject) {
      resolve("");
    })
      .then(res => {
        return Promise.resolve({ name: "dqhan" });
      })
      .then(res => {
        console.log(res);
      });

    解决callback回调地狱问题

    Promise对象特点:

    1状态不受外界影响

    2状态不可逆

    Promise实现方式
    简易版
    class Promise {
      callbacks = [];
      state = "pending";
      value = null;
      constructor(fn) {
        fn(this._resolve.bind(this));
      }
      then(onFulfilled) {
        if (this.state === "pending") {
          this.callbacks.push(onFulfilled);
        } else {
          onFulfilled(this.value);
        }
      }
      _resolve(value) {
        this.state = "fulfilled";
        this.value = value;
        this.callbacks.forEach(fn => fn(value));
      }
    }

    添加链式调用

    class Promise {
      callbacks = [];
      state = "pending";
      value = null;
      constructor(fn) {
        fn(this._resolve.bind(this));
      }
      then(onFulfilled) {
        if (this.state === "pending") {
          this.callbacks.push(onFulfilled);
        } else {
          onFulfilled(this.value);
        }
        return this;
      }
      _resolve(value) {
        this.state = "fulfilled";
        this.value = value;
        this.callbacks.forEach(fn => fn(value));
      }
    }

    在then中return了一个this,乍一看是对的,但是仔细想想,是不是整个链式调用返回的都是同一个对象,违背了Promise对象的意图,所以改进

    class Promise {
      callbacks = [];
      state = "pending";
      value = null;
      constructor(fn) {
        fn(this._resolve.bind(this));
      }
      then(onFulfilled) {
        return new Promise(resolve => {
          this._handle({
            onFulfilled: onFulfilled || null,
            resolve: resolve
          });
        });
      }
      _handle(callback) {
        if (this.state === "pending") {
          this.callbacks.push(callback);
          return;
        }
        if (!callback.onFulfilled) {
          callback.resolve(this.value);
          return;
        }
        var ret = callback.onFulfilled(this.value);
        callback.resolve(ret);
      }
      _resolve(value) {
        if (value && (typeof value === "object" || typeof value === "function")) {
          var then = value.then;
          if (typeof then === "function") {
            then.call(value, this._resolve.bind(this));
            return;
          }
        }
        this.state = "fulfilled";
        this.value = value;
        this.callbacks.forEach(callback => this._handle(callback));
      }
    }

    Over~

  • 相关阅读:
    Linux ps命令
    SecureCRT注册机使用方法
    微信消息的处理和应答
    微信公众号开发--开发服务器接入微信服务器
    RESTful架构
    OAuth2.0详解
    HTTP头详解
    Cookie/Session机制详解
    学习tornado:安全
    python tornado框架实现CRUD
  • 原文地址:https://www.cnblogs.com/moran1992/p/14730219.html
Copyright © 2020-2023  润新知