Мне удается решить это, используя цикл while.
for (let appUrl of appUrls) {
var count = i++;
while(true){
try{
await page.goto(appUrl);
const appName = await page.$eval('div.det-name-int', div => div.innerText.trim());
console.log('\n' + count);
console.log('Name: ' , appName);
break;
} catch(e){
console.log('\n' + count);
console.log('ERROR');
await page.reload(appUrl);
continue;
}
}
Любым другим способом сделать это просто был бы более неловкий синтаксис для исправления обезьяны. Существуют способы включить send
и eval
и все виды вещей, но почему? Идите вперед и сделайте это очевидный путь.
Вы хотите остерегаться исправления обезьяны в больших проектах или когда у Вас есть зависимости, потому что можно волновать с конфликтами, когда несколько рук все бездельничают в том же месте. Это не означает, ищут альтернативный синтаксис, который выполняет то же самое — это означает быть осторожным при внесении изменений, которые могли влиять на код, это не Ваше. Это, вероятно, не беспокойство в Вашем особом случае. Это - просто что-то, что, возможно, должно было бы быть обращено в больших проектах.
Одна альтернатива в Ruby - то, что можно добавить методы к отдельному объекту.
a = "Hello"
b = "Goodbye"
class <<a
def to_slang
"yo"
end
end
a.to_slang # => "yo"
b.to_slang # NoMethodError: undefined method `to_slang' for "Goodbye":String
Если Вы хотите добавить новый метод, который доступен для каждого строкового объекта, то, делая его способ, которым у Вас есть он, состоит в том, как сделать его.
Хорошая практика должна поместить Ваши расширения базовых объектов в отдельном файле (как string_ex.rb
) или подкаталог (как extensions
или core_ext
). Таким образом, очевидно, что было расширено, и для кого-то легко видеть, как они были расширены или изменены.
То, где исправление обезьяны может разложиться, - когда Вы изменяете некоторое существующее поведение базового объекта, который вызывает некоторый другой код, который ожидает, что исходная функциональность будет неправильно себя вести.
Спасибо, ребята.
Вся предложенная работа реализации. Что еще более важно, я учился весить в случае в руке и решать при повторном открытии ядра (или библиотека), классы являются хорошей идеей или нет.
FWIW, друг, на которого указывают send
реализация я искал. Но теперь, когда я смотрю на него, это еще ближе к monkeypatching, чем все другие реализации :)
module M
def do_magic
....
end
end
String.send(:include, M)
object
класс определяет send
, и все объекты наследовали это. Вы "отправляете" объект send
метод. send
параметры метода являются именем method-you-want-to-invoke как символом, сопровождаемым любыми аргументами и дополнительным блоком. Можно также использовать __send__
.
>> "heya".send :reverse
=> "ayeh"
>> space = %w( moon star sun galaxy )
>> space.send(:collect) { |el| el.send :upcase! }
=> ["MOON", "STAR", "SUN", "GALAXY"]
Править..
Вы, вероятно, хотите использовать define_method
метод:
String.class_eval {
define_method :hello do |name|
self.gsub(/(\w+)/,'hello') + " #{name}"
end
}
puts "Once upon a time".hello("Dylan")
# >> hello hello hello hello Dylan
Это добавляет методы экземпляра. Добавить методы класса:
eigenclass = class << String; self; end
eigenclass.class_eval {
define_method :hello do
"hello"
end
}
puts String.hello
# >> hello
Вы не можете определить методы, которые ожидают блок все же.
Это могла бы быть хорошая вещь иметь чтение этой главы из того, Почему Острое Руководство, Вы, может пропустить вниз к Массиву "Dwemthy" для получения до материала метапрограммирования.