先看这样一个例子:

function foo() {var result;$.ajax({url: '...',success: function(response) {result = response;}});return result;
}var result = foo(); // It always ends up being `undefined`.

在这个例子中,使用ajax进行异步请求,但是响应的返回值始终是undefined。那这是什么原因呢?这个问题最初也让我很困惑。下面我们来分析一下原因。

找出问题的原因

我们知道ajax中的a代表异步,那就意味着发送请求(亦或是接受响应)需要花费一点时间。而在上述例子中,$.ajax是被立即返回的,return result; 这句语句在success 函数返回响应前就已经被执行了。主要原因还是没有理解异步和同步之间的区别。

下面这个类比希望可以使同步和异步的区别更清晰。

Synchronous(同步流)

想象你给你的一个朋友打电话,你希望他可以帮你一个忙,你会进行一段时间的等待,直到他的回答。

那么在正常同步流的代码中也会发生一样的事情。

function findItem() {var item;while(item_not_found) {// search}return item;
}var item = findItem();// Do something with item
doSomethingElse();

执行 findItem 需要花费一段时间,所有在 var item = findItem(); 这条语句之后的代码都需要等待函数返回结果。

Asynchronous(异步流)

同样你又给你的朋友打了一个电话,但是现在你很忙,你给你的朋友留言让他给你回一个电话,然后你挂掉电话就做其他的事情了,直到你的朋友回你电话,你才会停下手中的事情处理这个电话。

这也正是ajax请求的过程。

findItem(function(item) {// Do something with item
});
doSomethingElse();

不去等待响应而是立即继续执行ajax之后的语句。而为了得到响应我们会定义一个回调函数,一旦收到响应就会执行这个回调函数。但是注意在ajax请求之后的语句会在回调函数调用前被执行。

解决问题的方法

1. 使用回调函数

上面的例子中

var result = foo();
// Code that depends on 'result'

改为

foo(function(result) {// Code that depends on 'result'
});

然后我们给 foo 传递函数参数

function myCallback(result) {// Code that depends on 'result'
}foo(myCallback);

函数 foo 定义如下

function foo(callback) {$.ajax({// ...success: callback});
}

一旦ajax 请求成功,$.ajax 就会调用callback 函数并且将响应传递给callback 函数。

2.使用promise

Promise API是ES6新特性之一,但是各大浏览器已经有了很好的支持(IE11及以上支持)。MDN这么定义它:

Promise 对象用于异步计算。一个 Promise 表示一个现在、将来或永不可能可用的值

promise的语法:

new Promise(/* executor */function(resolve, reject) {...}
);

这里是一段使用promise 的例子:

function delay() {// `delay` returns a promisereturn new Promise(function(resolve, reject) {// Only `delay` is able to resolve or reject the promisesetTimeout(function() {resolve(42); // After 3 seconds, resolve the promise with value 42}, 3000);});
}delay().then(function(v) { // `delay` returns a promiseconsole.log(v); // Log the value once it is resolved
}).catch(function(v) {// Or do something else if it is rejected // (it would not happen in this example, since `reject` is not called).
});

结合ajax 使用:

function ajax(url) {return new Promise(function(resolve, reject) {var xhr = new XMLHttpRequest();xhr.onload = function() {resolve(this.responseText);};xhr.onerror = reject;xhr.open('GET', url);xhr.send();});
}ajax("/echo/json").then(function(result) {// Code depending on result
}).catch(function() {// An error occurred
});

这里有关于promise 的更多信息。

3.jQuey: 使用延迟函数

jQery的延迟函数和promise 很像,但是API略有不同。每一个jQery的ajax方法都会返回一个延迟函数。

function ajax() {return $.ajax(...);
}ajax().done(function(result) {// Code depending on result
}).fail(function() {// An error occurred
});

始终要牢记promise 和延迟函数都只有一个存有未来值 的容器而不是值本身。看下面的例子:

function checkPassword() {return $.ajax({url: '/password',data: {username: $('#username').val(),password: $('#password').val()},type: 'POST',dataType: 'json'});
}if (checkPassword()) {// Tell the user they're logged in
}

这段代码就误解了异步和延迟过程,$.ajax() 会向服务器发送对/password 的请求,jQery内部机制会立即会返回一个ajax延迟函数,而这个并不是服务器发回来的响应。这也就意味着下面的判断语句(if)始终都是true,程序会认为读者已经登录,而这是不正确的。

我们可以进行一个小的修改:

checkPassword()
.done(function(r) {if (r) {// Tell the user they're logged in} else {// Tell the user their password was bad}
})
.fail(function(x) {// Tell the user something bad happened
});

现在我们仍然会向服务器发起请求,$.ajax() 也会立即返回一个延迟对象,但是我们通过监听.done().fail() 事件能正确处理服务器返回的响应。.done() 事件被调用时,服务器返回的是一个正常的响应(http 200),我们通过检查他的返回对象是否为true判断用户是否登陆。
.fail() 处理函数是处理一些错误的事件。例如用户网络断开或服务器错误等。

本文代码均来自StackOverflow上这个话题。

转载于:https://www.cnblogs.com/syqcoding-life/p/9821762.html

关于异步请求的一些事相关推荐

  1. 架构设计|异步请求如何同步处理?

    来自:程序通事 本文创意来自一次业务需求,这次需要接入一个第三方外部服务.由于这个服务只提供异步 API,为了不影响现有系统同步处理的方式,接入该外部服务时,应用对外屏蔽这种差异,内部实现异步请求同步 ...

  2. 异步请求 ajax的使用详解

    异步交互和同步交互 要说Ajax就不得不说,异步传输和同步传输了. 异步是值:发送方发出数据后,不等接收方发回响应,接着发送下一个数据包的通讯方式. 同步是指:发送方发出数据后,等待接收方发回响应以后 ...

  3. 动手撸一个金馆长表情库——爬虫及异步请求

    前言:对于一些社交达人,微信或者QQ斗图几乎家常便饭.然而许多人手机里却只有那么几个表情,这样怎么在表情大战中取胜呢?不过不要忘了,我们是程序猿,没有弹药库自己造呗!于是就有了这篇文章. 项目gith ...

  4. http异步请求方式

    问题来了: 上一篇文章讲解了http的同步请求,如果需要在主线程中做多个http同步请求,必定阻塞耗费大量的时间,严重影响用户体验.那么问题来了,该如何解决呢? 解决方案: 此时我们可以将http同步 ...

  5. php处理异步请求_php的异步请求操作

    php的异步请求操作 PHP #异步请求2012-04-15 00:21 在很多情况下,有这样的一个需求:让php在后台执行某个程序,但要让页面快速的输出显示. 以下是我总结的几种实现方式 exec ...

  6. JSD-2204-同步和异步请求-Ajax-Day13

    1.同步请求和异步请求 同步: 指单线程依次做几件事 异步: 指多线程同时做几件事 同步请求: 指客户端只有一个主线程,既要负责页面展示相关也要负责发请求获取数据, 由于只有一个线程当发出请求时则不再 ...

  7. 同步请求和异步请求(利用axios)

    文章目录 同步请求和异步请求 客户端如何发出异步请求? GET和POST 选择 利用GET方式 异步请求Get 运行环境环境:springboot+SpringMVC+Mybatis+vue 前端 后 ...

  8. iOS 中的网络请求 (同步请求、异步请求、GET请求、POST请求)

    1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...

  9. 第106天:Ajax中同步请求和异步请求

    同步请求和异步请求的区别 1.同步是指:发送方发出数据后,等接收方发回响应以后才发下一个数据包的通讯方式. 用户填写所有信息后,提交给服务器,等待服务器的回应(检验数据),是一次性的.信息错误又要重新 ...

最新文章

  1. .NET之生成数据库全流程
  2. ZeroC ICE源代码中的那些事 - 嵌套类和局部类
  3. VMware的CentOS部署环境
  4. 190719每日一句
  5. 基于STM32单片机设计指纹考勤机+上位机管理
  6. java生成背景透明的png图片,Java生成背景透明的png图片
  7. 【Unity】在Scene窗口中发射射线
  8. 无盘服务器4根网线雨两根网线的区别,网线接法的描述:实际用到4根。
  9. Python-猫耳MF
  10. Python(八)阶段小结
  11. java基础-取余数,取商
  12. 手机支付:合作之路才是正途
  13. 安卓搭建http服务器——NanoHttpd
  14. otter异常——zookeeper重新初始化
  15. 2022年全球市场硬化疗法总体规模、主要企业、主要地区、产品和应用细分研究报告
  16. 高德地图是直线距离吗_是直线直线
  17. 2021011206贾天乐实验五
  18. 带随机种子的javascript随机函数
  19. Visual Studio 2019 性能探查器使用
  20. Unable to find a version of the runtime to run this application解决方法

热门文章

  1. python读取文件多行内容-使用python读取.text文件特定行的数据方法
  2. python爬虫从入门到精通-Python爬虫从入门到精通视频(2018新版)
  3. python类型-python语言中的数据类型有哪些
  4. mapreduce编程实例python-Python模拟MapReduce的流程
  5. python源代码不需要编译成什么-python程序不需要编译吗
  6. python中可以用中文作为变量-在python字典中使用变量作为键名
  7. python快速入门答案-总算懂得python脚本快速入门教程
  8. python错误-Python错误和异常(error)处理技巧
  9. python语法教程-Python语言的核心语法(1)(语法教程)(参考资料)
  10. python散点图拟合曲线-Python解决最小二乘法拟合并绘制散点图