1

I have the following code on which I am trying to block the execution of the method _saveAddress multiple time, so I made a promise for this method.

const [pressEventDisabled, setPressEventDisabled] = useState(false);

<TouchableOpacity style={style.button_container} activeOpacity={1} disabled={pressEventDisabled} onPress={async () => {setPressEventDisabled(true); await _saveAddress(); setPressEventDisabled(false);}} >

The problem is that I want to resolve the promise after the callback method it's executed. It's there any way to wait for the dispatch function to execute or to resolve the promise inside the callback method?

This is the method for saving the address:

const _saveAddress = () => new Promise(async (resolve) => {
    var valid = _validate();
    if (valid) {
        const address = createAddressJson();
        if (addressId) {
            var addressIdProperty = {
                id: addressId
            };
            const newAddress = Object.assign(addressIdProperty, address);
            dispatch(editAddress(newAddress, _onAddressSaveEditCallback));
        } else {
            dispatch(addAddress(address, _onAddressSaveEditCallback));
        }
    } else {
        //notify
        notifyMessage(strings.fill_required_inputs_validation);
        resolve();
    }
});

This is the callback method:

const _onAddressSaveEditCallback = async (success: boolean, apiValidations: any, address ? : Address, ) => {
    if (success) {
        if (typeof callback == 'function') {
            callback(address);
        }
        await Navigation.pop(componentId);
    } else {
        setDataValidations(apiValidations);
    }
};
Rahul Bhobe
  • 4,165
  • 4
  • 17
  • 32
Ioana B
  • 195
  • 3
  • 16
  • `new Promise(async (....` ...never a sign of good code ... the executor of a promise should never be an async function - suggests you're doing something wrong – Jaromanda X Sep 03 '20 at 22:57
  • as written, that promise will only resolve if, when you call it, `_validate()` returns false ... so when `await _saveAddress()` is called, it will await forever if `_validate()` returns true – Jaromanda X Sep 03 '20 at 22:59
  • [Never pass an `async function` as the executor to `new Promise`](https://stackoverflow.com/q/43036229/1048572)! – Bergi Sep 03 '20 at 23:03
  • What do `editAddress` and `addAddress` do? It looks like these should be the functions returning promises (instead of taking callbacks) – Bergi Sep 03 '20 at 23:04
  • I am saving data on the server with those ones, and then with the response I receive I call the callback method. – Ioana B Sep 03 '20 at 23:11

1 Answers1

1

Just do exactly what you say in the title. Nothing more, nothing less:

if (addressId) {
    var addressIdProperty = {id: addressId};
    const newAddress = Object.assign(addressIdProperty, address);
    dispatch(editAddress(newAddress, async (s,v,a) => {
        await _onAddressSaveEditCallback(s,v,a);
        resolve();
    }));
} else {
    dispatch(addAddress(address, async (s,v,a) => {
        await _onAddressSaveEditCallback(s,v,a);
        resolve();
    }));
}

Of course, since you are passing async () => {} to addAddress instead of _onAddressSaveEditCallback you have to call _onAddressSaveEditCallback yourself since addAddress will be calling the async () => ...


But mixing promises and callbacks like this isn't great. It leads to weird looking and sometimes confusing code. A better solution is to promisify addAddress:

function addAddressPromise (address) {
    return new Promise((resolve, reject) => {
        addAddress(address, (success, validations, address) {
            if (success) return resolve(address);
            else reject(validations)
        });
    });
}

Now you can wait for addAddress:

const _saveAddress = async () => {
    // Don't create new promise here, we do it in addAddress..

    // ...

    let result = await addAddressPromise(address);
    dispatch(result);
    await _onAddressSaveEditCallback();

    // ...

}
Ioana B
  • 195
  • 3
  • 16
slebetman
  • 109,858
  • 19
  • 140
  • 171