循环内的多个 AJAX 请求并构建数组

Multi AJAX requests inside a loop and building an array

我完全卡住了。我想完成以下任务: 登录和注销时使用正确的价格协议更新购物车。

  1. 从 LocalStorage 获取当前 cartlines(成功)
  2. 每个 cartline 都有一个 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)+'}');
});
}

我假设你想要什么:

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

$.getJSON方法returnsjqXHR object, which implements the 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 初始数组中的顺序相同.

下面是异步处理数组并等待处理完成的完整代码段。请注意,我在我的代码片段中创建了 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();

如果您认为每个项目都是一个 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
}