Как вызвать функцию, когда ее аргументы приходят из разных мест - PullRequest
0 голосов
/ 31 мая 2019

Я хочу вызвать функцию (showResult), но каждый из ее обязательных аргументов происходит из разных мест. Мне нужно подождать, пока обработчик события (сервер отправит ответ) для цены, но не знаю, как я должен передать другой необходимый аргумент (продукт).

РЕДАКТИРОВАТЬ: Чтобы уточнить, server.onResponse ссылается на обработчик события "onmessage" соединения websocket ( ссылка )

function requestPhoneCost () {
    var product = "iPhone 7";
    server.requestPrice(product);
}

server.onResponse(function(response) {
   //response contains only information about the price, but not
   //what product its for

   showResult( , response.price);

});

function showResult (product, cost) {
   alert(product + " costs " + response + "dollars");
}




Ответы [ 2 ]

1 голос
/ 31 мая 2019

Основная проблема здесь server. Это, по-видимому, общий ресурс, но он имеет только один обратный вызов, который вызывается с ответами. Этот дизайн не будет работать.

Вместо этого сервер должен принять обратный вызов для определенного вызова с запросом. Тогда делать то, что вы ищете, тривиально:

function requestPhoneCost () {
    var product = "iPhone 7";
    server.requestPrice(product, cost => showResult(product, cost));
}

В современном мире я бы использовал обещания, а не обратный вызов с ручным кодированием:

function requestPhoneCost () {
    var product = "iPhone 7";
    server.requestPrice(product)
    .then(cost => showResult(product, cost))
    .catch(error => { /* handle/report error */);
}

В обоих случаях это требует изменения server, поэтому он отслеживает, какие обратные вызовы относятся к каким запросам. Это звучит намного сложнее, чем на самом деле (это на самом деле очень просто), но мы не можем помочь вам с кодом, который мы не видим (например, код server).

Вы сказали, что в конструкторе соединения через веб-сокет настроен центральный onResponse. IIRC, каждое сообщение в веб-сокете имеет уникальный идентификатор (и, если нет, предположительно, вы можете добавить его). После этого вы можете сохранить информацию об обещании, которое вы вернули для запроса, в Map с указанием этого ID:

this.id = 0; // If you need to assign your own IDs
this.settlersById = new Map();

Вот концептуальный requestPrice метод в вашем классе сервера:

requestPrice(product) {
    const id = ++this.id;
    const promise = new Promise((resolve, reject) => {
        sendRequest({id, product});
        this.settlersById.set(id, {resolve, reject});
    });
}

затем в ответе

onResponse(response) {
    const {id} = response;
    const settlers = this.settlersById.get(id;
    if (settlers) {
        this.settlersById.delete(id);
        if (/* response is a success */) {
            resolve(response.data);
        } else {
            reject(/*...appropriate error...*/);
        }
    }
}

Опять же, это все концептуально, так как у нас нет класса вашего сервера. И он использует свой собственный идентификатор, в то время как websockets может предоставить один для вас.

1 голос
/ 31 мая 2019

Объявите функцию ответа в функции requestPhoneCost, чтобы она могла получить доступ к product в замыкании.

function requestPhoneCost() {
  var product = "iPhone 7";
  server.requestPrice(product);
  server.onResponse(function(response) {
    showResult(product, response.price);
  });
}

function showResult(product, cost) {
  alert(product + " costs " + response + "dollars");
}

Предполагается, что server.onResponse() заменяет прослушиватель события ответа вместо добавления дополнительного прослушивателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...