Я нашел решение этой проблемы.
Чтобы решить проблему:
1- Нет проблем, когда я использую какие-либо обещания в своем коде. 2. Нет проблем, когда я использую angularfire-lite.
Таким образом, есть 2 решения: 1- Использование angularfire-lite
2- Использование кода node.js для серверной версии приложения. Я имею в виду файл "server.js" или "server.ts".
Я использую JavaScript для моего «серверного» файла. Поэтому я могу добавить код node.js в server.js для обновления тегов og. Для этого первым шагом является создание serve.js. Затем найдите, куда вы хотите добавить мета-теги. А потом развернуть. Вот и все. Результат примерно такой.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.database();
/*<<-Just for ssr*/
var SeoServiceService = /** @class */ (function () {
function SeoServiceService(titleService, meta, router) {
this.titleService = titleService;
this.meta = meta;
this.router = router;
}
SeoServiceService.prototype.generateTags = function (config) {
console.log('Client Side');
/*Just for ssr->>*/
return db.ref('test/ssr').on('value',(snapshot)=>{
console.log('Server Side');
this.meta.updateTag({ property: 'og:title', content: 'It works :)' });
return true
});
/*Just for ssr->>*/
console.log('Client Side');
};
SeoServiceService.ngInjectableDef = i0.defineInjectable({ factory: function SeoServiceService_Factory() { return new SeoServiceService(i0.inject(i1.Title), i0.inject(i1.Meta), i0.inject(i2.Router)); }, token: SeoServiceService, providedIn: "root" });
return SeoServiceService;
}());
«Server.js» - это большой и сложный файл. Трудно найти, где вы должны добавить свой код node.js. Одним из решений является добавление вашего node.js в качестве комментария к угловому коду. После создания 'server.js' просто найдите этот комментарий и сделайте его работоспособным. Например, мой угловой код приведен ниже. И окончательный результат выше кода.
import { Injectable } from '@angular/core';
import { Title, Meta } from '@angular/platform-browser';
import { Router } from '@angular/router';
/*Just for ssr->>*/
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const db = admin.database();
/*<<-Just for ssr*/
@Injectable({
providedIn: 'root'
})
export class SeoServiceService {
constructor(
private titleService: Title,
private meta: Meta,
private router: Router,
) { }
generateTags(config) {
console.log('Client Side');
/*Just for ssr->>
return db.ref('test/ssr').on('value',(snapshot)=>{
console.log('Server Side');
this.meta.updateTag({ property: 'og:title', content: 'It works :)' });
return true
});
Just for ssr->>*/
console.log('Client Side');
}}
Этот алгоритм интеллектуален и действительно минимизирует операции записи. Таким образом, значение длины будет сходиться к балансу между кратчайшей длиной и отсутствием столкновений.
Вы можете ослабить ограничение отсутствия столкновений, используя стратегии, используемые в хеш-таблицах. Попробуйте некоторые другие уникальные идентификаторы, прежде чем вернуться к увеличению длины.
Таким образом, я бы предложил вам добавить тестовый счетчик в конец строки хеширования, инициализированной в 0. Если сгенерированный идентификатор уже используется, увеличьте счетчик и повторите попытку, пока не будет достигнуто максимальное значение счетчика после увеличения длины.
В результате вы будете более эффективно использовать адресное пространство своего идентификатора и будете значительно реже увеличивать длину.
Относительно вашего вопроса об ограничении длины MD5, я думаю, что выбор MD5 - это перебор. Вам действительно не нужен криптографический (псевдо) безопасный хеш. Вам нужен генератор случайных битов, для которого вы можете использовать crc32 (или adler, который работает быстрее). Особенно, если код должен быть запущен на мобильном телефоне. Чтобы реализовать генератор случайных битов с помощью crc32, добавьте 32-битное значение к строке для хеширования и инициализируйте ее постоянным значением по вашему выбору (начальное число). Затем вычислите crc32 для этой строки. Если вам нужно больше байтов, запишите полученное значение crc32 в 32 бита перед строкой и пересчитайте crc32. Итерируйте, пока у вас не будет достаточно битов. Вам нужен генератор случайных битов, для которого вы можете использовать crc32 (или adler, который работает быстрее). Особенно, если код должен быть запущен на мобильном телефоне. Чтобы реализовать генератор случайных битов с помощью crc32, добавьте 32-битное значение к строке для хеширования и инициализируйте ее постоянным значением по вашему выбору (начальное число). Затем вычислите crc32 для этой строки. Если вам нужно больше байтов, запишите полученное значение crc32 в 32 бита перед строкой и пересчитайте crc32. Итерируйте, пока у вас не будет достаточно битов. Вам нужен генератор случайных битов, для которого вы можете использовать crc32 (или adler, который работает быстрее). Особенно, если код должен быть запущен на мобильном телефоне. Чтобы реализовать генератор случайных битов с помощью crc32, добавьте 32-битное значение к строке для хеширования и инициализируйте ее постоянным значением по вашему выбору (начальное число). Затем вычислите crc32 для этой строки. Если вам нужно больше байтов, запишите полученное значение crc32 в 32 бита перед строкой и пересчитайте crc32. Итерируйте, пока у вас не будет достаточно битов. запишите полученное значение crc32 в 32 бита перед строкой и пересчитайте crc32. Итерируйте, пока у вас не будет достаточно битов. запишите полученное значение crc32 в 32 бита перед строкой и пересчитайте crc32. Итерируйте, пока у вас не будет достаточно битов. Вы можете заменить crc32 алгоритмом по вашему выбору. Это дает дешевый и быстрый генератор случайных битов, где начальная константа является начальным числом.
С помощью этого алгоритма вы минимизируете количество генерируемых случайных битов, а также не имеете верхнего предела длины.
Что касается кодирования, вы не указали ограничения. Можете ли вы использовать прописные и строчные буквы с цифрами? В вашем примере используется алфавит из 36 различных значений ASCII. Если у вас есть генератор псевдослучайных чисел, описанный выше, который может генерировать столько байтов, сколько необходимо, просто определите длину, чтобы быть числом букв вашего идентификатора, и выберите следующую букву по модулю следующего случайного байта. Тогда вы будете точно знать, сколько байтов генерировать за один раз, и генерация идентификатора тривиальна.
How about something like this:
If you want 4 character keys using a-zA-Z0-9, then you'd have: 62^4 = > 14 million possible values.
Break this up into N partitions: 0000 ... 1000, 1001 ... 2000 , ... , ZZAA ... ZZZZ
Each partition is represented by an entity with: start id end id current id
Now, to generate an ID:
использовать текущий идентификатор, который был сохранен в качестве вашего идентификатора.
Если вы выберете N равным 140, у каждого раздела будет 100 000 значений. Это позволило бы довольно много одновременных вставок при ограничении количества повторных попыток из-за выбора «пустого» раздела.
Возможно, вам нужно подумать об этом больше. Особенно, как вы справитесь со случаем, когда вам нужно перейти на 5 или 6-значные клавиши?
-Dave
Просто для того, чтобы добавить некоторые жесткие числа к вопросу выше, я реализовал небольшую программу для генерации идентификаторов в соответствии с линиями, упомянутыми в вопросе, и это были результаты одного из пробных прогонов :
Length Count MD5 Base 62
4 400 3d0e 446
5 925 4fc04 1Myi
6 2434 0e9368 40V6
7 29155 e406d96 GBFiA
8 130615 7ba787c8 2GOiCm
9 403040 75525d163 YNKjL9
10 1302992 e1b3581f52 H47JAIs
Total: 1869561
Каждый раз, когда длина хеша увеличивалась, это происходило из-за столкновения, поэтому в этом случае было шесть столкновений. Количество - это количество ключей заданной длины, которые были сгенерированы до столкновения. Столбец MD5 показывает последний усеченный ключ, который был успешно добавлен до того, как произошла ошибка дублированного ключа. В крайнем правом столбце показан ключ в базе 62 (если я правильно сделал преобразование).
Похоже, что с каждым дополнительным символом генерируется все больше и больше ключей, что вы и представляете. Я надеюсь, что этот подход будет масштабироваться для пользовательского контента.
Для всех, кто интересуется, вот как я получил представление base 62 для последнего столбца:
def base_62_encode(input):
"Inspired by code at http://en.wikipedia.org/wiki/Base_36."
CLIST="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
rv = ""
while input != 0:
rv = CLIST[input % 62] + str(rv)
input /= 62
return rv
base62_id = base_62_encode(long(truncated_hash, 16))
(Добавлено позже:)
Вот класс, который заботится о нескольких вещах, связанных с генерацией этих идентификаторов. в контексте Google App Engine. По умолчанию ключи, сгенерированные этим классом, не являются чисто базовыми 62, поскольку первый символ имени ключа GAE должен быть буквенным. Это требование было решено с помощью базы 52 для первого символа.
Первичная база может быть изменена на что-то, отличное от 62, путем изменения значения «clist», которое было передано (или опущено) в конструкторе. Возможно, вы захотите удалить символы, которые легко перепутать, например, «1», «l», «i» и т. Д.
Использование:
keygen = LengthBackoffIdGenerator(SomeClass, initial_length=5)
small_id, modified = keygen.small_id(seed_value_from_sharded_counter)
Вот класс:
class LengthBackoffIdGenerator(object):
"""Class to generate ids along the lines of tinyurl.
By default, ids begin with a alphabetic character. Each id that is created is checked against previous ones
to ensure uniqueness. When a duplicate is generated, the length of the seed value used is increased by one
character.
Ids become gradually longer over time while remaining relatively short, and there are very few retries in
relation to the number of keys generated.
"""
ids = set()
def __init__(self, cls, clist='0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ', alpha_first=False,
initial_length=5, check_db=False):
self.clist = clist
self.alpha_first = alpha_first
if self.alpha_first:
import re
alpha_list = re.sub(r'\d', '', clist)
if len(alpha_list) < 1:
raise Exception, 'At least one non-numeric character is required.'
self.alpha_list = alpha_list
self.cls = cls
self.length = initial_length
self.check_db = check_db
def divide_long_and_convert(self, radix, clist, input, rv):
"Inspired by code at http://en.wikipedia.org/wiki/Base_36."
rv += clist[input % radix]
input /= radix
return (input, rv)
def convert_long(self, input):
rv = ""
if self.alpha_first:
input, rv = self.divide_long_and_convert(len(self.alpha_list), self.alpha_list, input, rv)
while input != 0:
input, rv = self.divide_long_and_convert(len(self.clist), self.clist, input, rv)
return rv
def hash_truncate_and_binify(self, input, length):
"""Compute the MD5 hash of an input string, truncate it and convert it to a long.
input - A seed value.
length - The length to truncate the MD5 hash to.
"""
from assessment.core.functions import md5_hash
input = md5_hash(input)[0:length]
return long(input, 16)
def _small_id(self, input):
"""Create an ID that looks similar to a tinyurl ID.
The first letter of the ID will be non-numeric by default.
"""
return self.convert_long(self.hash_truncate_and_binify(input, self.length))
def small_id(self, seed):
key_name = self._small_id(seed)
increased_length = False
if self.check_db and not self.cls.get_by_key_name(key_name) is None:
self.ids.add(key_name)
if key_name in self.ids:
self.length += 1
increased_length = True
key_name = self._small_id(seed)
self.ids.add(key_name)
return (key_name, increased_length)