TypeError: PromiseReject called on non-object at reject
产生这个错误的原因是因为我编写了如下代码
const newTask = oldTask.then(Promise.reject)
导致报错的原因是 Promise.reject内部依赖上下文(context), 只要改成 Promise.reject.bind(Promise)就可以了.
按惯性思维, 大多数原生方法都是不依赖 this的, 例如: Array.isArray, 就可以通过 const isArray = Array.isArray; isArray([]); 的方式调用.
在 React Native 中压缩图片至指定大小之下
tag: [React Native]
首先分析现有函数可完成的功能:
- 获取某图片文件大小, 以及其体积(width, height)
- 压缩图片至指定比率
在有了上述两个条件后就可以愉快的编写代码了, 压缩流程如下
-
判断是否小于指定文件大小
-
小于, 不需要压缩
-
大于, 尝试压缩为原有质量的 80%, 判断是否小于指定文件大小
-
小于, 返回压缩后的图片文件
-
大于, 继续缩小质量
-
如果压缩次数过多, 这时可能无法压缩了, 则直接缩小原始图片文件的尺寸(width, height), 再次缩小质量, 直到文件体积小于指定大小
// 是否小于指定的文件大小 (单位为 MB) export const isLessThanTheMB = (fileSize: number, smallerThanSizeMB: number) => { const isOk = fileSize / 1024 / 1024 < smallerThanSizeMB; return isOk; };
// 获取文件详情 export const inspectFile = (fileURI: string) => { return FileSystem.getInfoAsync(fileURI); };
/**
- 压缩图片
- @param fileURI - 文件路径
- @param limitMB - 最大文件大小, MB 为单位 */ export const imageCompress = async (fileURI: string, limitMB: number) => { // 先不实现 Web 压缩了 if (!AppEnvs.isNative) { return manipulateAsync( fileURI, [], { compress: 0.5 } ) }
let fileInfo = await inspectFile(fileURI);// 先给一个初始值, 避免不需要压缩的情况 let imageResult: ImageResult = await manipulateAsync( fileInfo.uri, [], { compress: 1 } ); let compress = 0.9 while (!isLessThanTheMB(fileInfo.size, limitMB)) { console.log("当前文件大小", fileInfo.size / 1024 / 1024); console.log("压缩比率", compress); if (compress < 0.1) { console.log("压缩率已至最低, 无法压缩, 尝试缩小图片尺寸"); compress = 1 imageResult = await manipulateAsync( fileInfo.uri, [{ resize: { width: imageResult.width * 0.5, height: imageResult.height * 0.5 } }], { compress: compress } ); } else { imageResult = await manipulateAsync( fileInfo.uri, [], { compress: compress } ); // 每次减少 20% 的体积 compress = compress * 0.7; } fileInfo = await inspectFile(imageResult.uri); } return imageResult};
textTransform 的用法以及不适用场景
tag: [React Native]
官方文档, 虽然官方文档没有详细写出该属性的用法, 但是凭借名称, 我们可以大概猜到
TYPE
DEFAULT
enum('none', 'uppercase', 'lowercase', 'capitalize')
'none'
-
none
-
默认值, 不对文字做转换
-
uppercase
-
将所有字母大写, 如果有多个字母(通过空格分割)
-
Hello word -> HELLO WORLD
-
Helloword -> HELLOWORLD
-
lowercase
-
与
uppercase行为相反 -
capitalize
-
将首字母大写
-
Hello word -> Hello World
-
Helloword -> Helloworld
上述的用法已经覆盖了 90% 的使用场景, 但是仍然有种场景无法覆盖, 那就是将 Usa payment转换为 USA Payment即一个非标准单词 + 标准单词转换为 非标转单词全大写, 标准单词首字母大写的情况, 不过这是一个合理的行为, 这里笔者也仅仅是做记录加深印象, 避免踩坑.
最后的最后, 因为 textTransform 没有提供文档描述, 本着求真的精神, 笔者去看了下源码
源码分析
所在位置: github.com/facebook/re…
可以发现, uppercase和 lowercase都是调用 java 的原生方法, capitalize则是 RN团队自定义的函数: 通过 BreakIterator对文本中的单词进行分割, 然后将首字母大写.
iOS 端的代码就不发了, 有兴趣自行阅读, 源码位置, 值得一提的是, 在 capitalize 模式下, Android 使用的是 BreakIterator来分割文本, 但是 iOS 是直接通过空格切分单词, 不知道会不会有什么坑.
package com.facebook.react.views.text;
import java.text.BreakIterator;
/** Types of text transforms for CustomTextTransformSpan */
public enum TextTransform {
NONE,
UPPERCASE,
LOWERCASE,
CAPITALIZE,
UNSET;
public static String apply(String text, TextTransform textTransform) {
if (text == null) {
return null;
}
String transformed;
switch (textTransform) {
case UPPERCASE:
transformed = text.toUpperCase();
break;
case LOWERCASE:
transformed = text.toLowerCase();
break;
case CAPITALIZE:
transformed = capitalize(text);
break;
default:
transformed = text;
}
return transformed;
}
private static String capitalize(String text) {
BreakIterator wordIterator = BreakIterator.getWordInstance();
wordIterator.setText(text);
StringBuilder res = new StringBuilder(text.length());
int start = wordIterator.first();
for (int end = wordIterator.next(); end != BreakIterator.DONE; end = wordIterator.next()) {
String word = text.substring(start, end);
if (Character.isLetterOrDigit(word.charAt(0))) {
res.append(Character.toUpperCase(word.charAt(0)));
res.append(word.substring(1).toLowerCase());
} else {
res.append(word);
}
start = end;
}
return res.toString();
}
};
Avoid prop drilling 中 drilling 的翻译
tag: [ 英语]
今天查阅英语文章时, 遇到了一个新的单词组 Avoid prop drilling, 要理解这个单词组就要先理解 React(Vue)中 props传递层级过深所导致的问题, 例如 Vue 文档中所提到的
这里的
组件可能其实根本不关心这些 props,但它仍然需要定义并将它们传递下去使得 能访问到这些 props,如果组件链路非常长,可能会影响到更多这条路上的组件。这一过程被称为“prop drilling”,这似乎不太好解决。drilling:
v.
钻孔,打眼;操练,训练;(drill的现在分词)
复数: drills
原形: drill
第三人称单数: drills
现在分词: drilling
过去式: drilled
过去分词: drilled
关于为什么使用 drilling单词, 而没有使用 Deep transmission(深层传递) 等更容易理解的原因, 我的理解如下:
假如现在组件树为
-
Root
-
A#1
-
A#1-1
-
A#1-2
-
A#1-2-1
-
B
-
C
这里 A#1-2-1想要从 Root获取某些值就很困难, 那么到底有多难呢? 就像要从 A#1-2-1钻一个洞(drilling) 到 Root一样困难.
而这个单词组的重点也恰恰是突出, props在多级传递时的困难.
LOL 瞎理解的不知道对不对..