专栏首页LIN_ZONEjs中的异步与同步,解决由异步引起的问题

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. 命名函数 清除嵌套回调的一个便捷的解决方案是简单的避免双层以上的嵌套。传递一个命名函数给作为回调参数,而不是传递匿名函数 例:  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 });
 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 });
  1. 使用promise promise在异步执行的流程中,把执行代码和处理结果的代码清晰地分离了:

promise还可以做若干个异步的任务,例:有一个异步任务,需要先做任务1,如果任务成功后再做任务2,任何任务失败则不再继续并执行错误处理函数。 job1.then(job2).then(job3).catch(handleError);  //job1、job2和job3都是Promise对象 例: 关于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仍在继续执行,但执行结果将被丢弃。

 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 });

本文参考:

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

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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • css 使元素居中

    <div style="text-align:center;">居中显示</div>

    lin_zone
  • js将图片转换为base64

    lin_zone
  • js 图片与base64互相转换

    参考地址:http://www.cnblogs.com/mr-wuxiansheng/p/6931077.html

    lin_zone
  • CSS隐藏元素的方法

    使用CSS隐藏元素的主要方式有diaplay: none;、opacity: 0;、visibility: hidden;、position: absolute...

    WindrunnerMax
  • 三方库源码笔记(12)-OkHttp / Retrofit 开发调试利器

    在使用 OkHttp 或者 Retrofit 的时候,我觉得大部分开发者会做得最多的自定义实现就是拦截器了。因为 OkHttp 的拦截器真的是太有用了,我们的很...

    业志陈
  • underscore 诞生记(一)—— 基本结构搭建

    underscore 是一款成熟可靠的第三方开源库,正如 jQuery 统一了不同浏览器之间的 DOM 操作的差异,让我们可以简单地对 DOM 进行操作,und...

    小皮咖
  • 【DB笔试面试648】在Oracle中,当自动收集任务运行时,哪些对象会被收集?

    存在缺失和陈旧的统计信息的表、索引和分区会被收集。当自动收集任务运行时,优先收集缺失统计信息的对象,然后再收集陈旧统计信息的对象。可以从DBA_TAB_STAT...

    小麦苗DBA宝典
  • 编写自己的代码库(javascript常用实例的实现与封装--续)

    这个系列的上一篇文章(编写自己的代码库(javascript常用实例的实现与封装))总结了34个常见的操作。但是在开发中,常见的实例又何止这么多个,经过这些日子...

    守候i
  • 使用 Commitizen 撰写 Angular 规范的 Commit Message

    用 git cz -m 代替 git commit -m 就可以轻松的写出 Angular 规范的 commit message 了。

    Theo Tsao
  • 【系列】移动端项目经验 表单兼容(上篇)

    移动端 表单兼容(上篇) HTML5学堂:从这篇文章开始,我们将为大家总结介绍移动端的常见兼容问题,今天要提的是关于表单的一些兼容问题,本文主要包括input文...

    HTML5学堂

扫码关注云+社区

领取腾讯云代金券