js am besten, wie man nach zwei asynchronen AJax-Vorgängen einen neuen Vorgang ausführt
世界只因有你
世界只因有你 2017-07-05 10:54:02
0
11
1696

Ich bin heute auf eine Interviewfrage gestoßen: Wenn es auf der Seite zwei asynchrone Ajax-Operationen gibt, weil die Ausführungsreihenfolge dieser beiden asynchronen Operationen nicht sicher ist, wie kann ich eine neue Operation ausführen, nachdem beide Operationen ausgeführt wurden? ist die Methode?

Ich habe damals Methode eins beantwortet: Verschachteln Sie zwei Ajaxe und führen Sie neue Operationen in der Rückgabefunktion des zweiten Ajaxes aus. Antwort des Interviewers: Diese Methode ist zu lahm.

Also dachte ich über die zweite Antwort nach: Überwachen Sie lokale Variablen über den Timer setTimeout und stellen Sie sicher, dass die beiden asynchronen Vorgänge abgeschlossen sind, bevor Sie einen neuen Vorgang ausführen. Antwort des Interviewers: Die Leistung dieser Methode ist nicht gut. Können Sie sich eine einfachere und vernünftigere Methode vorstellen?

Ich habe damals nicht darüber nachgedacht
Also habe ich diese Frage gestellt, um herauszufinden, was der beste Weg ist? Willkommen zur Diskussion und Beratung

世界只因有你
世界只因有你

Antworte allen(11)
学习ing

1.Promise 包装异步ajax操作,
2.定义async 函数,
3.用await等待promise数据异步获取完成
这一种方法简洁高效,下面请看我专门给你写的示例代码
我懒得用ajax获取数据了,就用settimeout这个函数模拟获取数据吧,这个函数是异步的,原理效果一样。

//模拟ajax异步操作1
function ajax1() {
    const p = new Promise((resolve, reject) => {
        setTimeout(function() {
            resolve('ajax 1 has be loaded!')
        }, 1000)
    })
    return p

}
//模拟ajax异步操作2
function ajax2() {
    const p = new Promise((resolve, reject) => {
        setTimeout(function() {
            resolve('ajax 2 has be loaded!')
        }, 2000)
    })
    return p
}
//等待两个ajax异步操作执行完了后执行的方法
const myFunction = async function() {
    const x = await ajax1()
    const y = await ajax2()
        //等待两个异步ajax请求同时执行完毕后打印出数据
    console.log(x, y)
}
myFunction()
漂亮男人

http://api.jquery.com/jQuery....

为情所困

目前浏览器环境中开箱即用的原生方法是 Promise.all。

以调用我的地图库 Sinomap Demo 为例,这个页面中为了加载一张地图,需要多个同时发起但不能确保返回顺序的请求:

  1. 中国地形数据

  2. 各省份数值 JSON 数据

  3. 多种图表叠加时多种图表存在多种 JSON 数据需通过不同数据接口返回……

解决方法直接在未打包的 http://sinomap.ewind.us/demo/demo.js 中,示例:

// 封装地形 GeoJSON 数据接口
// 将每个数据接口封装为一个返回 Promise 的函数
function getArea () {
  return new Promise((resolve, reject) => {
    fetch('./resources/china.json').then(resp =>
      resp.json().then(china => resolve(china))
    )
  })
}

// 封装分色地图数据接口
function getPopulation () {
  return new Promise((resolve, reject) => {
    fetch('./resources/china-population.json').then(resp =>
      resp.json().then(data => resolve(data))
    )
  })
}

// 封装城市数据接口
function getCity () {
  return new Promise((resolve, reject) => {
    fetch('./resources/city.json').then(resp =>
      resp.json().then(data => resolve(data))
    )
  })
}

// 使用 Promise.all 以在三个数据接口均异步成功后,执行回调逻辑
Promise.all([getArea(), getPopulation(), getCity()]).then(values => {
  // 依次从返回的数据接口数组中获取不同接口数据
  let china = values[0]
  let population = values[1]
  let city = values[2]
  // 使用数据
  doWithData(china, population, city)
})

这样通过 Promise 不仅实现了回调逻辑的解耦,还实现了基础的异步流程控制。

小葫芦

刚刚看到jquery 的 when 方法,所以给你重写了一个,不一定有jquery的那么好,但至少能实现效果了,可以在控制台直接输入下述代码试试,我勒个去,写了我整整半小时。。

function ajax(callback){
    callback = callback || function(){};
    var xhr = new XMLHttpRequest();
    xhr.open("get","");
    xhr.onload = function(res){ callback(res) };
    xhr.send(null); 
}

var when = (function(){
    var i = 0,
        len = 0,
        data = [];
    return function(array,callback){
        callback = callback || function(){};
       len = len || array.length;
        var fn = array.shift();
       
       fn(function(res){
            i++;
            data.push(res);
            if(i < len){
                when(array,callback);
            } else {
                callback(data);
            } 
       });   
    };
})();

when([ajax,ajax],function(data){
    console.log(data);
});
给我你的怀抱

问下能不能用jQ,能用的话直接:

$.when($.ajax("page1"), $.ajax("page2")).done(function(){});

顺带给个$.when的文档参考

为情所困

我觉得是Promise的方法 all还是什么的

学习ing

你的问题是有三件事 a,b,c。c要在a和b结束之后再执行。

有很多方法: 比如你说的嵌套法 还有暴力监听法

这个问题我曾经考虑过,以下是我的解答。

异步发射器

用数组保存如何执行异步操作

注意里面的函数都有个参数 commit ,它是一个函数 用来回传值。 当ajax成功的时候 把返回值回传进去就好

// 两个异步操作  
var todos = [
    function getUser(commit){ 
        setTimeout(() => {
            commit({  // 这里是异步结束的时候 利用 commit 把值回传 
                name: 'eczn',
                age: 20
            }, 233); 
        }); 
    },
    function getLoc(commit){
        setTimeout(() => {
            commit({
                area: '某个地方'
            });
        }, 333); 
    }
]; 

编写发射器

processors 是 todos 这样的数据。 cb 是最终回调。

function launcher(processors, cb){
    var o = {}; 
    var count = 0; 
    if (processors.length === 0) cb(o); 

    processors.forEach((func, idx) => {
        func(function commit(asyncVal){ // 这就是commit函数 
            // 把 asyncVal 的所有属性合并到 o 上 
            // ( 利用 Object.keys 获取对象全部属性名 )
            Object.keys(asyncVal).forEach(key => {
                o[key] = asyncVal[key]; 
            }); 
            
            // 计数器自加 
            count++; 
            // 如果发射器全部发射完毕则调用回调函数 cb 并把 o 作为参数传递
            if (count === processors.length) cb(o); 
        }); 
    }); 
}

并发他们

执行异步发射器 并提供 最终回调

launcher(todos, function(whereEczn){
    // todos 里面存放的异步操作的值由 commit 回调返回
    // 全部回调跑完的时候 就会执行当前这段函数 并把期望值返回
    console.log(whereEczn); 

    // 按顺序输出
    ['name', 'area'].forEach(key => {
        console.log(`${key}: ${whereEczn[key]}`); 
    }); 
});

Link

https://eczn.coding.me/blog/%...

世界只因有你

可以定义个变量a=0,ajax请求成功后在回调里设置a++;
然后在两个回调中均判断下a==2 执行操作函数

Peter_Zhu

设置两个flag,然后两个ajax调用同一个回调,在这个回调中判断两个flag都为true才执行后续操作。

漂亮男人

把ajax写在另一个ajax里面再在回调那里执行

Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage