之前在项目中遇到过好多次因为异步引起的变量没有值,所以意识到了认识js中同步与异步机制的重要性

在单线程的js中,异步代码会被放入一个事件队列,等到所有其他代码执行后再执行,而不会阻塞线程。

下面是js几种最常见的异步情况:

  1. 异步函数 setTimeout和setInterval
    异步函数,如setTimeout和setInterval,被压入了称之为Event Loop的队列。
    setTimeout:在指定的毫秒数后,将定时任务处理的函数添加到执行队列的队尾。所以有时候也可以使用setTimeout解决异步带来的问题
    setInterval:按照指定的周期(以毫秒数计时),将定时任务处理函数添加到执行队列的队尾。

    Event Loop是一个回调函数队列。当异步函数执行时,回调函数会被压入这个队列。JavaScript引擎直到异步函数执行完成后,才会开始处理事件循环。这意味着JavaScript代码不是多线程的,即使表现的行为相似。事件循环是一个先进先出(FIFO)队列,这说明回调是按照它们被加入队列的顺序执行的。
  2. ajax
  3. node.js中的许多函数也是异步的

解决由的js异步引起的问题办法:

  1. 命名函数
    清除嵌套回调的一个便捷的解决方案是简单的避免双层以上的嵌套。传递一个命名函数给作为回调参数,而不是传递匿名函数
    例:

     var fromLatLng, toLatLng;
    var routeDone = function( e ){
    console.log( "ANNNND FINALLY here's the directions..." );
    // do something with e
    };
    var toAddressDone = function( results, status ) {
    if ( status == "OK" ) {
    toLatLng = results[0].geometry.location;
    map.getRoutes({
    origin: [ fromLatLng.lat(), fromLatLng.lng() ],
    destination: [ toLatLng.lat(), toLatLng.lng() ],
    travelMode: "driving",
    unitSystem: "imperial",
    callback: routeDone
    });
    }
    };
    var fromAddressDone = function( results, status ) {
    if ( status == "OK" ) {
    fromLatLng = results[0].geometry.location;
    GMaps.geocode({
    address: toAddress,
    callback: toAddressDone
    });
    }
    };
    GMaps.geocode({
    address: fromAddress,
    callback: fromAddressDone
    });

    async.js 库可以帮助我们处理多重Ajax requests/responses,如:

     async.parallel([
    function( done ) {
    GMaps.geocode({
    address: toAddress,
    callback: function( result ) {
    done( null, result );
    }
    });
    },
    function( done ) {
    GMaps.geocode({
    address: fromAddress,
    callback: function( result ) {
    done( null, result );
    }
    });
    }
    ], function( errors, results ) {
    getRoute( results[0], results[1] );
    });
  2. 使用promise
    promise在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了:

    promise还可以做若干个异步的任务,例:有一个异步任务,需要先做任务1,如果任务成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。
    job1.then(job2).then(job3).catch(handleError);  //job1job2job3都是Promise对象

    例:

     'use strict';
    
     var logging = document.getElementById('test-promise2-log');
    while (logging.children.length > 1) {
    logging.removeChild(logging.children[logging.children.length - 1]);
    } function log(s) {
    var p = document.createElement('p');
    p.innerHTML = s;
    logging.appendChild(p);
    }
    // 0.5秒后返回input*input的计算结果:
    function multiply(input) {
    return new Promise(function (resolve, reject) {
    log('calculating ' + input + ' x ' + input + '...');
    setTimeout(resolve, 500, input * input);
    });
    } // 0.5秒后返回input+input的计算结果:
    function add(input) {
    return new Promise(function (resolve, reject) {
    log('calculating ' + input + ' + ' + input + '...');
    setTimeout(resolve, 500, input + input);
    });
    } var p = new Promise(function (resolve, reject) {
    log('start new Promise...');
    resolve(123);
    }); p.then(multiply)
    .then(add)
    .then(multiply)
    .then(add)
    .then(function (result) {
    log('Got value: ' + result);
    });

    关于promise的两个方法

     var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
    });
    var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
    });
    // 同时执行p1和p2,并在它们都完成后执行then:
    Promise.all([p1, p2]).then(function (results) {
    console.log(results); // 获得一个Array: ['P1', 'P2']
    });
     var p1 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 500, 'P1');
    });
    var p2 = new Promise(function (resolve, reject) {
    setTimeout(resolve, 600, 'P2');
    });
    Promise.race([p1, p2]).then(function (result) {
    console.log(result); // 'P1'
    });
    //由于p1执行较快,Promise的then()将获得结果'P1'p2仍在继续执行,但执行结果将被丢弃。

本文参考:

http://blog.csdn.net/u013063153/article/details/52457307

https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014345008539155e93fc16046d4bb7854943814c4f9dc2000

js中的异步与同步,解决由异步引起的问题的更多相关文章

  1. js中style.display=""无效的解决方法

    本文实例讲述了js中style.display=""无效的解决方法.分享给大家供大家参考.具体解决方法如下: 一.问题描述: 在js中我们有时想动态的控制一个div显示或隐藏或更多 ...

  2. Python并发编程06 /阻塞、异步调用/同步调用、异步回调函数、线程queue、事件event、协程

    Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件event.协程 目录 Python并发编程06 /阻塞.异步调用/同步调用.异步回调函数.线程queue.事件 ...

  3. 深入理解 JS 引擎执行机制(同步执行、异步执行以及同步中的异步执行)

    首先明确两点: 1.JS 执行机制是单线程. 2.JS的Event loop是JS的执行机制,深入了解Event loop,就等于深入了解JS引擎的执行. 单线程执行带来什么问题? 在JS执行中都是单 ...

  4. JS中for循环变量作用域--解决for循环异步执行的问题

    被这个问题困惑了很久,终于在网上找到了答案,感谢~ 现在分享给大家~ js中如何让一个for循环走完之后,再去执行下面的语句? 这涉及for循环变量作用域的问题,js中作用域只有函数作用域和全局作用域 ...

  5. js文件引用方式及其同步执行与异步执行

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp74   任何以appendChild(scriptNode) 的方式引入 ...

  6. js中奇怪的问题 同步ajax,modal遮罩层

    奇怪问题一 今天有一段js执行的时候出现了问题 $.ajax({ ..., async:false, ... }); $('#myModal').modal('hide'); loadcurrentp ...

  7. UML建模中简单消息、同步消息和异步消息

    两种消息在UML图中的表示方法如图: 1.同步方式 两个通信应用服务之间必须要进行同步,两个服务之间必须都是正常运行的.发送程序和接收程序都必须一直处于运行状态,并且随时做好相互通信的准备. 发送程序 ...

  8. js中toFixed精度问题的解决办法

    toFixed() 方法可把 Number 四舍五入为指定小数位数的数字.例如将数据Num保留2位小数,则表示为:toFixed(Num):但是其四舍五入的规则与数学中的规则不同,使用的是银行家舍入规 ...

  9. JS中多个onload冲突解决办法

    一  多个window.onload冲突 在一个页面中有两个JavaScript 分别都用到了window.onload一个是:window.onload=externallinks,另一个是:win ...

  10. 记录js中的兼容问题及解决办法

    1.获取非行内样式的兼容问题: 2.获取事件对象的兼容问题: 3.事件冒泡的兼容: 4.keyCode的兼容问题: 5.处理默认事件的兼容问题: 6.事件的绑定兼容问题:

随机推荐

  1. centos7 快速安装 mariadb(mysql)

    从最新版本的linux系统开始,默认的是 Mariadb而不是mysql! 使用系统自带的repos安装很简单: yum install mariadb mariadb-server systemct ...

  2. 安装配置Xdebug模块详解

    1.XDebug安装配置 (1)下载XDebug下载地址:http://www.xdebug.org/必须下载跟机器上安装的php匹配的版本才行.具体下载方法如下:将phpinfo网页的源代码拷贝到h ...

  3. 巧用watch命令执行循环操作,来解放我们的双手

    有时候我们需要重复执行某个 命令,观察某个文件和某个结果的变化情况.可以写 脚本去实现这些需求,但是有更简单的方法,本文档要介绍的就是watch 命令. 1. 以固定时间反复执行某个命令 root@j ...

  4. MultipartFile文件编码判断

    MultipartFile文件编码判断 搜索:Java 判断文件的字符集编码 https://blog.csdn.net/top_code/article/details/8891796 但是在Mul ...

  5. 构建分布式Tensorflow模型系列:CVR预估之ESMM

    https://zhuanlan.zhihu.com/p/42214716 本文是“基于Tensorflow高阶API构建大规模分布式深度学习模型系列”的第五篇,旨在通过一个完整的案例巩固一下前面几篇 ...

  6. 【网络安全】SSLSplit实现中间人攻击

    中间人攻击,即在中间监听获取网络数据以便获取的有价值的信息实现攻击破坏的目的,即client-mid man-server,此处介绍的sslsplit可以作为mid man监听ssl信息及HTTP信息 ...

  7. Python 3安装MySQLdb

    Python 2安装的是mysql-python,Python 3安装mysql-python以后,仍然不能import MySQLdb,原来Python 3应该安装mysqlclient,就可以im ...

  8. JAVA与C#的区别

    Java和C#都是编程的语言,它们是两个不同方向的两种语言 相同点: 他们都是面向对象的语言,也就是说,它们都能实现面向对象的思想(封装,继承,多态) 区别: 1.c#中的命名空间是namespace ...

  9. Git diff结果显示分析

    1.diff的三种格式: 正常格式(normal diff) 上下文格式(context diff) 合并格式(unified diff) 2.示例文件为了便于讲解,先新建两个示例文件.第一个文件叫做 ...

  10. 4 Git 基础 - 撤消操作

    撤消操作 任何时候,你都有可能需要撤消刚才所做的某些操作.接下来,我们会介绍一些基本的撤消操作相关的命令.请注意,有些撤销操作是不可逆的,所以请务必谨慎小心,一旦失误,就有可能丢失部分工作成果. 修改 ...