JS的异步编程的思考

发布时间:2019-08-15 发布网站:脚本宝典
脚本宝典收集整理的这篇文章主要介绍了JS的异步编程的思考脚本宝典觉得挺不错的,现在分享给大家,也给大家做个参考。

JS是一个富含回调的语言,最近在ajax和弹窗的问题上(之前在Node项目中读取文件和运行SQL中也遇到过这种问题)遇到了JS进程无法阻断的问题

问题:依赖函数返回值进行下一步的操作

  1. 例如datagrid的onBeforeSave这种依赖onBeforeSave的返回值来判断是否继续执行下边的save操作,如果这个返回值需要发送Ajax根据返回值来判断的话,或者需要根据用户输入来判断true或者false的情况下,就GG了
  2. node运行sql的时候,突发奇想把sql运行封装成一个方法,调用的时候传进去SQL语句然后函数返回值为sal结果。这时候SQL的运行是异步的,导致返回值一直为空
  3. ajax在这种情况下会被强制的改成同步,这样的修改是负优化,然后还会造成外部变量无法释放,为什么呢
function returnAjax(){
    let results = [];
    
    $.ajax({
        'url': '.....',
        'tyPE': 'post'
        'aysn': false,
        'success': function (re){
            results = re; //外部引用类型变量的引用,妈的
        }
    })
    
    return results;
}

解决:异步编程

上来就是高大上的异步编程,说白了,要不就是回调,要不就是事件监听(订阅者模式,我是这么理解的),说明白一点,JS在浏览器里是不能进行进程阻断的(然而实际情况上是可以的)

之前考虑到使用while-true,例如下边这么写

function hinahina(){
    let results = [];
    let isEndAjax = false;
    
    $.ajax({
        'url': '.....',
        'type': 'post'
        'success': function (re){
            results = re; 
            isEndAjax = true;
        }
    });
    
    while(!isEndAjax){
        //... 阻断中
    }
    
    return results;
}

像这样的方式阻断就是自杀,因为知道程序进入了这个while,就会一直占据着线程,ajax执行完成后的回调根本没有机会执行

所以只有浏览器中那些BOM的弹窗方法(window对象下挂的那些alter的)会阻断js线程。所以异步改同步,走不通啊

  • 第一种:回调

    回调,没什么可说的,闭包什么的性能问题和引用类型传参的问题后边再说吧(另起一篇)

  • 第二种:promise

    第二种就把伟大ES6的PRomise摆上来,不按套路出牌,是因为我觉得啊,promise跟回调没什么区别,摆一个例子出来:

class MyPromise {
    constructor() {
        this.callbacks = [];
        console.LOG('构建新的异步对象!');
    }
    
    resolve(result) {
        this.complete('resolve', result);
    }
    
    reject(result){
        this.COMplete('reject', result)
    }
    
    complete(type, result) {
        while (this.callbacks[0]) {
            this.callbacks.shift()[type](result);
        }
    }
    
    then(successHandler, failedHandler){
        this.callbacks.push({
            resolve: successHandler,
            reject: failedHandler
        });
        return this;
    }
    
}

然后怎么使用呢

let mp = new MyPromise();


let delay1 = () => {
    setTimeout(() => {
        console.log(111);
        mp.resolve('111执行!');
    });
    return mp;
};

delay1().then(function (msg) {
    console.log(msg)
});

看的出来,每个delay扔回一个promise实例,然后.the会把参数中的方法推到promise实例的callbacks执行队列里,然后当这个实例执行resolve的时候(或者执行reject),才会执行.then穿进去的方法。

感觉就像先把回调写好,然后等着异步执行这个回调。

  • 第三种:订阅者

为什么把 “发布/订阅” 放在这,因为看完promise再看 “发布/订阅” 就更好理解了,先写好订阅(类似于先写好回调),然后再在异步执行的代码里进行发布(类似于promise的resolve啥啥的),这样看就和promise一样了。

下面粘上阮的例子,jquery有类似的框架

jQuery.subscribe("done", f2); // 订阅

function F1(){

  setTimeout(function () {

    // f1的任务代码
    jQuery.publish("done"); // 发布

  }, 1000);

}

事件监听,这就是js的异步操作体现在事件驱动上了,其实看起来也类似 “发布/订阅” ,先定义一个事件(类似订阅),然后trigger这个事件(类似发布)

还是阮的例子:

f1.on('done', f2);

function f1(){

  setTimeout(function () {

    // f1的任务代码

    f1.trigger('done');

  }, 1000);

}

这样看来 所有的事件绑定和触发 都是一个异步操作。

@H_512_313@总结

总体来看,还是没有解决类似onBeforeSave这种限制在操作之前的事件回调,这种依赖onBeforeSave的返回值来判断是否执行下一步操作的情况下,onBeforeSave中绝对不能出现异步的操作。类似返回异步操作结果的方法也不能使用了(node运行sql)所以说老老实实用回调,不要过度依赖返回值

对于commonJS的规范,amD CMD的规范在另一篇中写。

脚本宝典总结

以上是脚本宝典为你收集整理的JS的异步编程的思考全部内容,希望文章能够帮你解决JS的异步编程的思考所遇到的问题。

如果觉得脚本宝典网站内容还不错,欢迎将脚本宝典推荐好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。