Harsh Jaswal
Harsh Jaswal

Reputation: 447

How to insert more than 5000 items in SharePoint list using JSOM?

I am trying to add 5000 items in a SharePoint list using JSOM. But unfortunately didn't get any luck.

function createListItem() {
    var clientContext = new SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle('DummyList');

    var itemCreateInfo = new SP.ListItemCreationInformation();
    for (var i = 0; i < 5000; i++) {
        this.oListItem = oList.addItem(itemCreateInfo);

        oListItem.set_item('ItemNumber', i);
        oListItem.update();
    }

    clientContext.load(oListItem);
    clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
}

function onQuerySucceeded() {
    console.log('Item created: ' + oListItem.get_id());
}

function onQueryFailed(sender, args) {
    console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

But after some time server stops responding. I know there is something called Threshold limit. But according to the requirement more than 5000 items should be stored in one take only. I have no idea where I am making mistake. Please help.

Upvotes: 1

Views: 1907

Answers (3)

Joshua Rose
Joshua Rose

Reputation: 390

Here is a combination of the two techniques.

async function createListItem() {
  const url = `${_spPageContextInfo.webAbsoluteUrl}/_api/web/lists/getbytitle('DummyListForMultiAdd')/items`;
  for (let index = 0; index < data.length; index += 100) {
    const finalNumber = index + 100 < data.length ? index + 100 : data.length;
    const batch = data.slice(index, finalNumber);
    const batchPromises = batch.map((d, i) => {
      d.__metadata = {
        type: "SP.Data.DummyListForMultiAddListItem"
      };
      d.ItemNumber = i + index;
      return xhr("post", url, d);
    })
    await Promise.all(batchPromises);
  }

  function xhr(type, url, data) {
    const prom = new Promise((res, rej) => {
      const xhr = new XMLHttpRequest();
      xhr.onreadystatechange = () => {
        if (xhr.readyState === XMLHttpRequest.DONE) {
          try {
            if (xhr.status === 200 || xhr.status === 201) {
              res(xhr.responseText);
            } else {
              const {
                status
              } = xhr;
              const name = "XHRError";
              const message =
                xhr.responseText ||
                "An error occured in sending or recieving the request";
              throw {
                status,
                name,
                message
              };
            }
          } catch (error) {
            if (error.status) {
              rej(error);
            } else {
              rej({
                status: 418,
                name: error.name,
                message: error.message
              });
            }
          }
        }
      };
      xhr.open(type, url);
      [{
          key: "Accept",
          value: "application/json;odata=verbose"
        },
        {
          key: "Content-Type",
          value: "application/json;odata=verbose"
        },
        {
          key: "X-RequestDigest",
          value: document.querySelector("#__REQUESTDIGEST").value
        }
      ].forEach(h => xhr.setRequestHeader(h.key, h.value));
      xhr.send(JSON.stringify(data));
    });
    return prom;
  }
}
createListItem()

Upvotes: 0

Harsh Jaswal
Harsh Jaswal

Reputation: 447

Somehow I found the solution for this. Instead of call back method I used REST API like this

function RestAdd()
{

      for(var i = 0 ; i < 5000; i++)
      {
$.ajax  
    ({  
    url: _spPageContextInfo.webAbsoluteUrl + "/_api/web/lists/getbytitle('DummyListForMultiAdd')/items",  
    type: "POST",
    async: false,
    data: JSON.stringify  
    ({  
        __metadata:  
        {  
            type: "SP.Data.DummyListForMultiAddListItem"  
        },  
        ItemNumber: i
    }),  
    headers:  
    {  
        "Accept": "application/json;odata=verbose",  
        "Content-Type": "application/json;odata=verbose",  
        "X-RequestDigest": $("#__REQUESTDIGEST").val(),  
        "X-HTTP-Method": "POST"  
    },  
    success: function(data, status, xhr)  
    { 
    console.log("success: "+i);
    },  
    error: function(xhr, status, error)  
    {  
        console.log("failed: "+i);
    }  
});
}
}

What I did is, I just used REST API with async:false. It adds your list items in a sync manner. In JSOM it works in async.

Upvotes: 0

Julien
Julien

Reputation: 119

Here is a suggestions. It does work on my environnements. It takes some times though (around 20 seconds) because all requested are queued by the server. You can probably play around with the batch limit to optimize numbers of requests.

function createListItem() {
    var clientContext = new SP.ClientContext.get_current();
    var oList = clientContext.get_web().get_lists().getByTitle('DummyList');

    var items = [];
    var batchLimit = 100;

    for (var i = 0; i < 5000; i++) {
        var itemCreateInfo = new SP.ListItemCreationInformation();
        var newItem = oList.addItem(itemCreateInfo);

        newItem.set_item('ItemNumber', i);
        newItem.update();
        items[i] = newItem;
        clientContext.load(items[i]);

        if (i % batchLimit == 0) {
            console.log("sending batch" + i / batchLimit);                                
            clientContext.executeQueryAsync(Function.createDelegate(this, this.onQuerySucceeded), Function.createDelegate(this, this.onQueryFailed));
            items = [];
        }            
    }
}

function onQuerySucceeded() {
    console.log('Item created');
}

function onQueryFailed(sender, args) {
    console.log('Request failed. ' + args.get_message() + '\n' + args.get_stackTrace());
}

Upvotes: 1

Related Questions