【问题标题】:Multi AJAX requests inside a loop and building an array循环内的多个 AJAX 请求并构建数组
【发布时间】:2021-02-17 21:36:33
【问题描述】:

我完全被困住了。我想完成以下任务: 在登录和退出时使用正确的价格协议更新购物车。

  1. 从 LocalStorage 获取当前购物车(成功)
  2. 对于每条购物车线路,都有一个 AJAX 请求(例如 getJSON)来取回当时适用的新数据。 (成功)
  3. 创建一个新对象并保存新数据。
  4. 将新对象添加到数组中。
  5. 当所有 AJAX 请求都准备好并且新数组 (new_cart) 完全填满后,再将其推送到 LocalStorage。

在我的脚本下方。我希望有人可以帮助我。

function sync() {

// Read LocalStorage
try {
  var dataArray = JSON.parse(getLocalStorage('cartarray'));
}
catch (err) {
  var dataArray = null;
}

ary1 = dataArray.cartlines;

var keys = Object.values(ary1);
        
        
// Delete LocalStorage
// unsetLocalStorage('cartarray');
        
new_cart1 = [];
$.each( keys, function( index, value ){  
    var itemUrl = "https://" + window.location.hostname + "/search/?sku=" + value.sku;
    var value1 = value.quantity;
    var p = $.getJSON(itemUrl);

    p.then(function(data) {
        var obj = {};
        
        // Add items
        obj['sku'] = data.results[0].sku;
        obj['quantity'] = value1;
        obj['price'] = data.results[0].price;
        obj['title'] = data.results[0].product_title;
        obj['img'] = data.results[0].img;
        obj['url'] = data.results[0].url;
        obj['internalSku'] = data.results[0].sku;

        // Return obj
        return obj;
    });
  
    // Add to object to array.
    new_cart1.push(obj);
});
        

$.when.apply($, new_cart1).then(function() { 
    var keys1 = new_cart1;
    var cartarray1 = [];
            
    for (var key of keys1) {
        console.log(key);
        if(key.quantity >= 1){
            cartarray1.push({
                sku: key.sku, 
                title: key.title,
                price: key.price,
                img: key.img,
                url: key.url,
                quantity: key.quantity,
                internalSku: key.internalSku,
                // custom: key.custom
            }); 
        }   
    }
    // setLocalStorage('cartarray', '{"cartId": "","cartlines":'+JSON.stringify(cartarray)+'}');
});
}

【问题讨论】:

  • 你可以promisify $.getJSON 请求hadler,然后使用Promise.all 等待服务器返回响应,之后你可以处理所有返回的结果。跨度>
  • @fen1x 你能提供我运行代码的结构吗?然后我明白如何进一步进行。

标签: jquery ajax promise .when


【解决方案1】:

如果您认为每个项目都是一个 async 方法,这一切都会简单得多

async function processItem(value) {
    var itemUrl = "https://" + window.location.hostname + "/search/?sku=" + value.sku;
    var data = await $.getJSON(itemUrl);

    return {
       sku: data.results[0].sku,
       quantity: value.quantity,
       price: data.results[0].price,
       title: data.results[0].product_title,
       img: data.results[0].img,
       url: data.results[0].url,
       internalSku: data.results[0].sku
    };        
}

然后等待它们就像在 map 的结果上执行 Promise.all 以获取值一样简单。以下代码同时运行它们并等待所有结果完成。

async function execute(){ 
    var dataArray = JSON.parse(getLocalStorage('cartarray'));
    var values = Object.values(dataArray.cartlines);
    var new_cart1 = await Promise.all(values.map(processItem));

    // do something with new_cart1 which is an array of 
    // the objects returned from processItem
}

【讨论】:

  • 谢谢Jamiec,你是怎么学会的?这是另一种很好的思考方式。
  • @nhatimme 我写代码已经很久了。
【解决方案2】:

我假设你想要什么:

  1. 你已经有一些dataArray
  2. 您希望为每个项目并行从服务器请求其他数据
  3. 完成所有请求后,您希望处理结果

$.getJSON方法返回jqXHR对象,它实现了Promise接口,所以你可以这样使用:

$.getJSON(someUrl).then(result => {
    // do something with result
});

或者这样(在async函数内部):

const result = await $.getJSON(someUrl);
// do something with result

下一步是使您的项目处理异步:

async function processItem(item) {
    return await $.getJSON(item.url);
}

并并行处理整个数组:

async function processArray(array) {
    const promises = array.map(processItem);
    return await Promise.all(promises);
}

请注意,Promise.all 解析为一个包含每个项目的结果的数组,results 的顺序与 promises 的初始数组中的顺序相同。

下面是完整的sn-p,它异步处理数组并等待处理完成。请注意,我在我的 sn-p 中创建了 asyncGetJson 占位符函数来模拟具有超时的真实服务器请求:

// Helper function to simulate random request timeout
function getRandomInt(min, max) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min) + min);
}

/**
 * Not a real request, just a placeholder
 * This function multiplies n by 2 and returns it after random timeout
 */
function asyncGetJson(n) {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve(n * 2);
    }, getRandomInt(500, 2000));
  });
}

async function processItem(item) {
  return await asyncGetJson(item);
}

async function processArray(dataArray) {
  const promises = dataArray.map(processItem);
  return await Promise.all(promises);
}

async function init() {
  const dataArray = [1, 2, 3];

  console.log('Start');
  const result = await processArray(dataArray);
  console.log(result);
  console.log('Done');

  // Here should be your logic that works with results from the server
}

init();

【讨论】:

  • $.getJSON 已经返回了一个承诺,无需将其包装在另一个中。 从 jQuery 1.5 开始,所有 jQuery 的 Ajax 方法都返回 XMLHTTPRequest 对象的超集。这个由 $.getJSON() 返回的 jQuery XHR 对象或“jqXHR”实现了 Promise 接口,为它提供了 Promise 的所有属性、方法和行为 api.jquery.com/jquery.getjson
  • @Jamiec Thx,我不知道。
猜你喜欢
  • 2010-12-14
  • 1970-01-01
  • 2023-03-09
  • 2016-10-15
  • 1970-01-01
  • 2019-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多