2

I have twelve items that need to be added to a list on button click. I am using the sp-pnp-js library to add items. But the function adds items to the list asynchronously.

I have tried many ways. But always failed. When I click the add-items-to-list button lets say 20 times, only 18 times the items are added to the list in correct order.

I have even tried promise. Please help.

Below is the code

twelveItemsToAdd.forEach((eachItem: any)=>{
pnp.sp.web.lists.getByTitle("ListName").items.inBatch(batch).add({ Col1: value1, Col2: value2
}); }); batch.execute().then(() => this._addMemberReview(PrjMemID));

  • You need to add 12 items in order or the order doesnt matter? – Mikel Jun 15 '18 at 7:22
  • Yes. It's mandatory. – Ashik Paul M Jun 15 '18 at 10:00
3

I didnt work with inBatch.

I will show you an example without it, and i guess you will be able to make it in the way you need.

Btw, your code isn't working as you want because you are not adding the elements when the previous element is already added, and some calls can end before the previous one.

Here is a function that you can use:

/**
 * Add an ordered array of elemets to a list. The elements should contain only the SP Columns
 * @param elements array of elements to add, with the item columns
 */
private addOrderedElements(elements: any[]): Promise<any> {
  return new Promise((resolve, reject) => {

    if (elements.length > 0) {
      // get first element of the array
      const element = elements[0];
      // remove the first element of the array
      elements.shift();
      pnp.sp.web.lists.getByTitle('Test').items.add(element).then(response => {
        console.log('then...', response);
        // call function again (first element removed before)
        return this.addOrderedElements(elements);
      }).catch(error => {
        console.log('catch...', error);
        reject(error);
      });
    } else {
      // no (more) items in array
      resolve(null);
    }

  });
}

The resolve and reject data you can change as you want.

This function can be reused in different lists because the item column structure is set outside the function.

How to call it:

    // elements to add
    // with EXACTLY the columns to set in SharePoint
    const elements = [
      {
        Title: 'el1',
      },
      {
        Title: 'el2',
      },
      {
        Title: 'el3',
      },
    ];

    // add all the elements ordered
    this.addOrderedElements(elements).then(response => {
      // all added correctly
      // do some stuff ...
      console.log('addOrderedElements-scs');
    }).catch(error => {
      // some error happened at some point...
      // handle the error ...
      console.log('addOrderedElements-catch');
    });

Simpler option with async and await

// call function
this.addOrderedElements2(elements);

// async function with await
private async addOrderedElements2(elements: any[]) {
  for (const element of elements) {
    await pnp.sp.web.lists.getByTitle('Test').items.add(element);
  }
}

Let me know if it helps you.

  • Thats nice!, ¿You used inBatch also or you didnt need to? – Mikel Jun 15 '18 at 10:46
  • inBatch was not required. – Ashik Paul M Jun 15 '18 at 10:47
  • Is there was to use both inBatch and await. Because the time taken is very long. If i can use inBatch I guess i can reduce the time taken. – Ashik Paul M Jun 15 '18 at 10:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.