关于异步请求的一些事

先看这样一个例子:

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 promise
  return new Promise(function(resolve, reject) {
        // Only `delay` is able to resolve or reject the promise
    setTimeout(function() {
      resolve(42);
        // After 3 seconds, resolve the promise with value 42
    }, 3000);
  });
}

delay().then(function(v) {
        // `delay` returns a promise
      console.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

时间: 2024-11-18 23:44:23

关于异步请求的一些事的相关文章

和浏览器异步请求取消相关的那些事

我们开发web页面时候,也许会遇到和异步请求取消相关的问题. 如:在一个请求发送之后,用户做了一个取消指令,为了节省资源,我们需要把已经被用户取消的请求终止掉:或者是一个页面正在用ajax请求后台,突然页面发生了跳转,而我们未完成的ajax莫名其妙地走进了error里面了. 为了解决这两问题,我们今天一起看看和异步请求取消相关的那些事. 1.ajax的取消 当我们创建一个XMLHttpRequest对象的时候,我们就会发现两个api——abert和onabort,这就是终止异步请求的方法与其响应

学习笔记12JS异步请求

*一般用JS来监听按钮事件,都应该先监听页面OnLoad事件. *Js写在哪里,就会在页面解析到哪里执行. 异步请求:所谓异步请求,就是使用JS来监听按钮点击事件,并且发送请求,等到回复后,再使用JS来进行页面跳转,或动态改变页面.使用场合:当请求是ashx是,都可以使用异步方法,页面就无需刷到ashx的一个空白页面或者不用于展示的页面了. *使用jquery发送异步请求:$("#按钮ID").Click(fuction(){ $.get( "页面URL.ashx"

jQuery基础(Ajax,load(),getJSON(),getScript(),post(),ajax(),同步/异步请求数据)

1.使用load()方法异步请求数据 使用load()方法通过Ajax请求加载服务器中的数据,并把返回的数据放置到指定的元素中,它的调用格式为: load(url,[data],[callback]) 参数url为加载服务器地址,可选项data参数为请求时发送的数据,callback参数为数据请求成功后,执行的回调函数. 2.使用getJSON()方法异步加载JSON格式数据 使用getJSON()方法可以通过Ajax异步请求的方式,获取服务器中的数据,并对获取的数据进行解析,显示在页面中,它的

ajax 异步请求四个步骤

ajax异步请求详解 ajxa定义:异步的JavaScript和xml 1.XMLHttpRequst的出现才有了异步处理 2.创建XmlHttpRequest对象 var request=new XMLHttpRequest(); 注意:如果要兼容IE6以下浏览器则需要编写如下代码 var request; if(window.XMLRequest){ request=new XMLRequestHttpRequest();  //IE7.IE8.360等 }else{ request=new

Ajax异步请求(二)

业精于勤,荒于嬉:行成于思,毁于随. ----致自己 目录: 二.jQuery四种常用的Ajax请求方式简介 1.$.ajax() 2.$.get() 3.$.post() 4.$.getJSON() ==================1.$.ajax()======================== jQuery在异步请求方面封装的较好,直接使用Ajax比较麻烦,jQuery大大简化了我们的使用,不用考虑浏览器之间的差异了. $.ajax()是jQuery底层ajax的实现,$.get()

js方式的异步请求

1 有的企业要求你要会写, 2 *1. 异步请求的get方式 3 代码: 4 //创建一个XmlHttpRequest请求 5 function createXmlHttpRequest(){ 6 //声明一个请求,并是设置为空 7 var xhr=null; 8 try{ 9 //兼容IE浏览器的请求 10 xhr=new ActiveXObject("microsoft.xmlhttp"); 11 }catch(e){ 12 try{ 13 //其他浏览器的请求对象 14 xhr=

让Flask处理异步请求

今天意外在网上看到一篇文章,写到 后端使用gunicorn+flask的方式,刚开始就直接使用flask跑,但是有一次就出现502了,发现由于flask是单进程处理请求的,不像Tornado的异步,同时访问的人数稍微过多,就会出现阻塞的情况,导致nginx出现502的问题 于是开始寻找flask处理异步请求的解决方案 首先 我不了解tornado的异步处理方式,有时间我会去了解一下 其次,我在实验里犯了一个错误,我随手用sleep(100)去做阻塞,造成的结果是整个进程被我挂起了,其实我只需要在

iOS ASI--同步和异步请求

1.添加ASI框架到项目 1>ASI框架在判断网络状态时,依赖于Reachability,可以在苹果的官方文档里找到,也可以ASI的Sample例子里找到. 2>添加ASI所依赖的类库: SystemConfiguration是Reachability所需要的类库 3>如果是ARC项目,还要在Targets-Compile Sources-Compiler Flags里把ASI的.m文件,都置为 -fno-objc-arc 4>最后编译程序,看成功否 2.发起请求 2.1同步请求

IOS之同步请求、异步请求、GET请求、POST请求(整理复习))

1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然可以对UI进行操作,程序可以继续运行 3.GET请求,将参数直接写在访问路径上.操作简单,不过容易被外界看到,安全性不高,地址最多255字节: 4.POST请求,将参数放到body里面.POST请求操作相对复杂,需要将参数和地址分开,不过安全性高,参数放在body里面,不易被捕获. 1.     同