Вместо того, чтобы бросать код на вас, есть два понятия, которые являются ключом к пониманию того, как JS обрабатывает обратные вызовы и асинхронность. (это даже слово?)
Есть три вещи, о которых вам нужно знать; Очередь; цикл события и стек
. В широких упрощенных терминах цикл событий подобен диспетчеру проекта, он постоянно прослушивает любые функции, которые хотят запускать и взаимодействовать между очереди и стека.
while (queue.waitForMessage()) {
queue.processNextMessage();
}
Как только он получает сообщение для запуска чего-то, он добавляет его в очередь. Очередь - это список вещей, которые ждут выполнения (например, ваш запрос AJAX). Представьте себе это так:
1. call foo.com/api/bar using foobarFunc
2. Go perform an infinite loop
... and so on
Когда одно из этих сообщений будет исполнено, оно выталкивает сообщение из очереди и создает стек, стек - это все, что нужно выполнить JS для выполнения инструкции в сообщение. Таким образом, в нашем примере ему говорят позвонить foobarFunc
function foobarFunc (var) {
console.log(anotherFunction(var));
}
. Так что все, что foobarFunc должно выполнить (в нашем случае anotherFunction
), будет вставлено в стек. исполняемый, а затем забытый - цикл события затем переместится на следующую вещь в очереди (или прослушивает сообщения)
. Главное здесь - порядок выполнения. Это
Когда вы совершаете вызов с использованием AJAX для внешней стороны или выполняете любой асинхронный код (например, setTimeout), Javascript зависит от ответ, прежде чем он сможет продолжить.
Большой вопрос, когда он получит ответ? Ответ в том, что мы не знаем, поэтому цикл событий ждет, когда это сообщение скажет: «Эй, забери меня». Если JS просто ждал этого сообщения синхронно, ваше приложение замерзнет, и оно сосать. Таким образом, JS продолжает выполнение следующего элемента в очереди, ожидая, пока сообщение не будет добавлено обратно в очередь.
Вот почему с асинхронной функциональностью мы используем вещи, называемые обратными вызовами. Это похоже на обещание буквально. Как и в I , обещание что-то вернуть в какой-то момент jQuery использует специальные обратные вызовы, называемые deffered.done
deffered.fail
и deffered.always
(среди других). Вы можете увидеть их все здесь
Итак, вам нужно передать функцию, которая в какой-то момент будет выполнена с переданными ей данными.
Поскольку обратный вызов не выполняется немедленно, но в более позднее время важно передать ссылку на функцию, которую она не выполнила. поэтому
function foo(bla) {
console.log(bla)
}
, поэтому большую часть времени (но не всегда) вы пройдете foo
не foo()
. Надеюсь, это будет иметь смысл. Когда вы сталкиваетесь с такими вещами, которые кажутся запутанными, я настоятельно рекомендую полностью прочитать документацию, чтобы хотя бы понять ее. Это сделает вас намного лучшим разработчиком.
Возможно, вы захотите попробовать plotmatrix:
library(ggplot2)
data(mtcars)
plotmatrix(mtcars[,1:3])
мне mpg (первый столбец в mtcars) не должен быть фактором. Я не проверял его, но нет причин, почему он должен быть таким. Однако я получаю график рассеяния:)
Примечание: для ссылки в будущем функция plotmatrix()
была заменена функцией ggpairs()
из пакета GGally
, поскольку @ naught101 предлагает в другом ответе ниже на этот вопрос.
Я все время хочу это делать, но сюжетница - это дерьмо. Hadley рекомендует , используя пакет GGally . Он имеет функцию ggpairs , которая представляет собой значительно улучшенный парный сюжет (позволяет использовать в ваших кадрах данные непрерывные переменные). Он отображает разные графики в каждом квадрате в зависимости от типов переменных:
library(GGally)
ggpairs(iris, aes(colour = Species, alpha = 0.4))
[/g3]
Если вы хотите получить объект ggplot
(а не ggmatrix
, как в случае ggpairs()
), решение состоит в том, чтобы дважды расплавить данные, а затем ggplot
с фасеткой. facet_wrap
будет лучше, чем facet_grid
при ограничении площади графика, если задан параметр scales = 'free'
.
require(ggplot2)
require(dplyr)
require(tidyr)
gatherpairs <- function(data, ...,
xkey = '.xkey', xvalue = '.xvalue',
ykey = '.ykey', yvalue = '.yvalue',
na.rm = FALSE, convert = FALSE, factor_key = FALSE) {
vars <- quos(...)
xkey <- enquo(xkey)
xvalue <- enquo(xvalue)
ykey <- enquo(ykey)
yvalue <- enquo(yvalue)
data %>% {
cbind(gather(., key = !!xkey, value = !!xvalue, !!!vars,
na.rm = na.rm, convert = convert, factor_key = factor_key),
select(., !!!vars))
} %>% gather(., key = !!ykey, value = !!yvalue, !!!vars,
na.rm = na.rm, convert = convert, factor_key = factor_key)
}
iris %>%
gatherpairs(Sepal.Length, Sepal.Width, Petal.Length, Petal.Width) %>% {
ggplot(., aes(x = .xvalue, y = .yvalue, color = Species)) +
geom_point() +
geom_smooth(method = 'lm') +
facet_wrap(.xkey ~ .ykey, ncol = length(unique(.$.ykey)), scales = 'free', labeller = label_both) +
scale_color_brewer(type = 'qual')
}