In a recent project where I was building a SPFx webpart using React Hooks, Typescript, Fluent UI and PNPjs, I found myself struggling to save a multiperson peoplepicker to a SharePoint list. The biggest difficulty I was having was the fact that I needed to make a call to ensureUser to retrieve a user id for each person selected in the peoplepicker before I could save the group of users to the SharePoint list.
The ensureUser calls are async calls, which adds another layer of difficulty to this dilemma. At first glance, you might think, just loop through the users and make the call to ensureUser. Sure, that seems logical, except that leaves no way to wait for all of the calls to complete before moving on. In fact, when attempting this, I always ended up with an empty array in my peoplepicker, because the browser started each ensureUser call and immediately went on to saving the data before any of the ensureUser calls ever completed.
What I needed was a way to make multiple async calls and wait for all of them to be complete before I could move on to saving that data. Enter Promise.all, my prince riding in on a white horse! Promise.all is a promise that takes an array of promises and resolves when all of the promises have resolved or rejects when one of the promises is rejected. Sounds magical, doesn’t it?! Let’s see it in action:
So what is happening here? I have created a function called saveListItem. It is important to note that this is an async function and you will need to use await when calling this function if you need to wait for it to resolve before moving on to whatever you are doing after it. It would look like this:
Inside the saveListItem function, you will see the magical Promise.all. I’m using await as I want to wait for Promise.all to resolve before moving on the the next bit of code. Promise.all is passed an array (selectedProject.ProjectTeam) of users. I map over the array and call ensureUser for each user to retrieve the userId. The result of the ensureUser call is then pushed to the userIds array.
Once all of the ensureUser calls have resolved, then the Promise.all resolves. The userIds array can then be used in the projectTeamId array, which will then be used to update the peoplepicker of the item in the SharePoint list.