crazy novice
crazy novice

Reputation: 1817

Promise chaining not working. Why?

I have following code to select multiple contacts and the filter only names that have XYZ. I am using then and done to accomplish this filter. In my contacts, there is one contact named XYZ Dude and I am selecting it also. Shouldn't this contact be passed in my done method after the filtering logic I apply in the then method? Any ideas what I may be doing wrong here

var picker = new Windows.ApplicationModel.Contacts.ContactPicker();

        // Open the picker for the user to select a contact.
        picker.pickMultipleContactsAsync().then(function (contacts) {
            var contactsStartingWithPrefixPa = contacts.filter(function filterContacts(contact) {
                if (contact.name.match(/XYZ/))
                    return true;
                return false;
            });
        }).done(function (contacts) {
            // code never reaches here
            if (contacts != null ) {
                contacts.forEach(function (contact) {
                    if (contact !== null) {
                        // logic to use this contact

                    }
                }
            )}
        });

Upvotes: 0

Views: 353

Answers (3)

Beetroot-Beetroot
Beetroot-Beetroot

Reputation: 18078

Unless there's a good reason to separate the filter from the "logic to use this contact", then both can be performed in one looping operation.

var picker = new Windows.ApplicationModel.Contacts.ContactPicker();

// Open the picker for the user to select a contact.
picker.pickMultipleContactsAsync().done(function(contacts) {
    if(contacts) {
        contacts.forEach(function(contact) {
            if(contact.name.match(/XYZ/)) {
                // logic to use this contact
            }
        });
    }
});

Otherwise, you're looping through contacts with .filter() then looping again with .forEach().

If you really must separate two aspects, then (assuming contacts has a .filter() method) you should be able to do so as follows :

var picker = new Windows.ApplicationModel.Contacts.ContactPicker();

// Open the picker for the user to select a contact.
picker.pickMultipleContactsAsync().then(function(contacts) {
    return contacts ? contacts.filter(function(contact) {
        return !!contact.name.match(/XYZ/);
    }) : [];
}).done(function(contacts) {
    contacts.forEach(function(contact) {
        // logic to use this contact
    });
});

Upvotes: 1

The return value from contacts.filter is not a promise, so you don't need to do any additional chaining here. Your code should look like this, as contactsStartingWithPrefixPa is simply a projection of contacts, so you can just do a forEach iteration directly:

        picker.pickMultipleContactsAsync().done(function (contacts) {
        var contactsStartingWithPrefixPa = contacts.filter(function filterContacts(contact) {
            if (contact.name.match(/XYZ/))
                return true;
            return false;
        })

        if (contactsStartingWithPrefixPa.length > 0) {
            contactsStartingWithPrefixPa.forEach(function (contact) {
                //Process
            });
        }
    });

Chaining of promises only works when each step of the chain (except the last) returns a new promise. If there isn't a promise to return, you don't have another async step so you can just process what you need right ther

Upvotes: 0

Sushil
Sushil

Reputation: 5535

return contactsStartingWithPrefixPa is required in the then function.

   // Open the picker for the user to select a contact.
    picker.pickMultipleContactsAsync().then(function (contacts) {
        var contactsStartingWithPrefixPa = contacts.filter(function filterContacts(contact) {
            if (contact.name.match(/XYZ/))
                return true;
            return false;
        return contactsStartingWithPrefixPa;
        });

Upvotes: 3

Related Questions