Promises aren't cancelable as such, but are cancelled in a limited sense by causing them to be rejected.
With that in mind, cancellation can be achieved with a small amount of elaboration around Promise.race() and the promise-returning function you wish to be cancelable.
function makeCancellable(fn) {
    var reject_; // cache for the latest `reject` executable
    return function(...params) {
        if(reject_) reject_(new Error('_cancelled_')); // If previous reject_ exists, cancel it.
                                                       // Note, this has an effect only if the previous race is still pending.
        let canceller = new Promise((resolve, reject) => { // create canceller promise
            reject_ = reject; // cache the canceller's `reject` executable
        });
        return Promise.race([canceller, fn.apply(null, params)]); // now race the promise of interest against the canceller
    }
}
Assuming your http call function is named httpRequest (promise is confusing):
const search = makeCancellable(httpRequest);
Now, each time search() is called, the cached reject executable is called to "cancel" the preceding search (if it exists and its race has not already fulfilled).
// Search 1: straightforward - nothing to cancel - httpRequest(200) is called
search(200)
.then(function() { console.log('search1 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });
// Search 2: search 1 is cancelled and its catch callback fires - httpRequest(2000) is called
search(2000)
.then(function() { console.log('search2 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });
// Search 3: search 2 is cancelled and its catch callback fires - httpRequest(1000) is called
search(1000)
.then(function() { console.log('search3 resolved') })
.catch(function(err) { console.log('search3 rejected', err) });
If necessary, the catch callbacks can test err.message === '_cancelled_' in order to distinguish between cancellation and other causes of rejection.