zoukankan      html  css  js  c++  java
  • js中的异步与同步,解决由异步引起的问题

    之前在项目中遇到过好多次因为异步引起的变量没有值,所以意识到了认识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. 命名函数
      清除嵌套回调的一个便捷的解决方案是简单的避免双层以上的嵌套。传递一个命名函数给作为回调参数,而不是传递匿名函数
      例:
       1 var fromLatLng, toLatLng;
       2 var routeDone = function( e ){
       3     console.log( "ANNNND FINALLY here's the directions..." );
       4     // do something with e
       5 };
       6 var toAddressDone = function( results, status ) {
       7     if ( status == "OK" ) {
       8         toLatLng = results[0].geometry.location;
       9         map.getRoutes({
      10             origin: [ fromLatLng.lat(), fromLatLng.lng() ],
      11             destination: [ toLatLng.lat(), toLatLng.lng() ],
      12             travelMode: "driving",
      13             unitSystem: "imperial",
      14             callback: routeDone
      15         });
      16     }
      17 };
      18 var fromAddressDone = function( results, status ) {
      19     if ( status == "OK" ) {
      20         fromLatLng = results[0].geometry.location;
      21         GMaps.geocode({
      22             address: toAddress,
      23             callback: toAddressDone
      24         });
      25     }
      26 };
      27 GMaps.geocode({
      28     address: fromAddress,
      29     callback: fromAddressDone
      30 });

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

       1 async.parallel([
       2     function( done ) {
       3         GMaps.geocode({
       4             address: toAddress,
       5             callback: function( result ) {
       6                 done( null, result );
       7             }
       8         });
       9     },
      10     function( done ) {
      11         GMaps.geocode({
      12             address: fromAddress,
      13             callback: function( result ) {
      14                 done( null, result );
      15             }
      16         });
      17     }
      18 ], function( errors, results ) {
      19     getRoute( results[0], results[1] );
      20 });
    2. 使用promise
      promise在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了:

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

      例:
       1 'use strict';
       2 
       3 var logging = document.getElementById('test-promise2-log');
       4 while (logging.children.length > 1) {
       5     logging.removeChild(logging.children[logging.children.length - 1]);
       6 }
       7 
       8 function log(s) {
       9     var p = document.createElement('p');
      10     p.innerHTML = s;
      11     logging.appendChild(p);
      12 }
      13 // 0.5秒后返回input*input的计算结果:
      14 function multiply(input) {
      15     return new Promise(function (resolve, reject) {
      16         log('calculating ' + input + ' x ' + input + '...');
      17         setTimeout(resolve, 500, input * input);
      18     });
      19 }
      20 
      21 // 0.5秒后返回input+input的计算结果:
      22 function add(input) {
      23     return new Promise(function (resolve, reject) {
      24         log('calculating ' + input + ' + ' + input + '...');
      25         setTimeout(resolve, 500, input + input);
      26     });
      27 }
      28 
      29 var p = new Promise(function (resolve, reject) {
      30     log('start new Promise...');
      31     resolve(123);
      32 });
      33 
      34 p.then(multiply)
      35  .then(add)
      36  .then(multiply)
      37  .then(add)
      38  .then(function (result) {
      39     log('Got value: ' + result);
      40 });

      关于promise的两个方法

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

    本文参考:

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

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

  • 相关阅读:
    vue中添加favicon.ico
    SEO 小技巧汇总
    vue中echarts随窗体变化
    vue加载Element ui地址省市区插件-- element-china-area-data
    Echarts 修改折线的颜色和折线的点的大小方法
    vue中添加swiper轮播插件
    Cannot find module 'object-keys' 的解决办法
    适用于所有页面的基础样式base.css
    git clone时的各种报错汇总
    css mix-blend-mode 颜色滤镜混合模式
  • 原文地址:https://www.cnblogs.com/zhuchenglin/p/7651990.html
Copyright © 2011-2022 走看看