JS как сделать что-то только один раз - PullRequest
0 голосов
/ 21 января 2019

Например:

// run this:
alert('Loading...');

// dont run this again:
alert('Loading...');

Я не хочу когда-либо повторять это. Как я могу сделать это с удобством (желательно без использования логических значений)?

Ответы [ 4 ]

0 голосов
/ 21 января 2019

Если вам нужна заводская функция, которая запоминает результат вызова функции с одним примитивным значением в качестве параметра, вы должны использовать Map:

const once = (() => fn => {
  const cache = new Map()
  return value => {
    if (!cache.has(value)) {
      cache.set(value, fn(value))
    }
    return cache.get(value)
  }
})()

function verboseSquare (value) {
  console.log('expensive calculation')
  return value * value
}

const squareOnce = once(verboseSquare)

console.log(squareOnce(4))
console.log(squareOnce(4)) // skipped work
console.log(squareOnce(5))
console.log(squareOnce(5)) // skipped work
0 голосов
/ 21 января 2019

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

var cache = [];

function do_once(task, fn) {
    if(cache.indexOf(task) == -1) { // shorthand: !~cache.indexOf(task)
        cache.push(task);
        return fn();
    }
}

Использование:

var alertLoading = alert.bind(null, "Loading...");

do_once("alert_loading", alertLoading); // will run

// later on...

do_once("alert_loading", alertLoading); // will not run again

Это работает до тех пор, пока вы даете каждому заданию, которое не хотите повторять другое имя.Независимо от функции, предоставленной в качестве второго аргумента do_once, она не будет работать, пока do_once уже вызван с тем же именем задачи.

0 голосов
/ 21 января 2019

Сначала создайте переменную для хранения информации о том, была ли функция уже запущена или нет (например, hasRun).Затем просто сохраните свою функциональность в условии if, которое проверяет, является ли эта переменная false.Вам нужно будет обновить эту переменную после первого запуска логики.

Это можно увидеть следующим образом:

hasRun = false;

document.getElementsByTagName('button')[0].addEventListener('click', function() {
  if (!hasRun) {
    console.log('Loading...'); // Gets run once
    hasRun = true; // Set the flag to true so the conditional doesn't get entered again
  } else {
    console.log('The function already ran!'); // Runs every subsequent time
  }
})
<button>Click me</button>
0 голосов
/ 21 января 2019

Стандартным способом является использование логического флага.

Но, если у вас есть отвращение к booleans, вы можете сделать это, переписав функцию, таким образом гарантируя, что ее буквально никогда больше не вызовут.

function loadButOnlyOnce() {
     console.log('This will only happen once!');
     loadButOnlyOnce = function() {};
}

loadButOnlyOnce();
loadButOnlyOnce();

Ваша среда IDE, вероятно, будет выдавать предупреждения в виде строки «Что вы делаете, это перезаписывает функцию!».Но это ваш код, и вы можете сделать это, если хотите.

Итак, теперь вы хотите общее решение, которое вы можете использовать с различными функциями?Вы можете сделать это так:

function allowOnlyOneCall(f) {
  return function() {
    f.apply(this, arguments);   
    f = function() {};
  }
}


function myMethod(p1) {
    console.log('myMethod is being invoked. p1 = ' + p1);
}

myMethod = allowOnlyOneCall(myMethod);


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