忽略块:要么我错了,要么威士忌开始起作用了。(我也不想排除我会变笨的可能性。很抱歉。)
预期:
我本来希望ReplaySubject每2秒返回一个值,因为我(每次)要等两秒钟才能调用next()
。
结果:
结果是等待2秒,但随后所有值都被同时输出。
有问题的代码在这里:
import { ReplaySubject } from 'rxjs';
export const rs$: ReplaySubject<number> = new ReplaySubject();
rs$.subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
complete: () => console.log('ReplaySubject completed'),
});
const fakeAPIValuesOne: Array<number> = [7, 11, 13];
fakeAPIValuesOne.forEach(async (entry: number) => {
await wait(2000); // <--- Why does wait() not work?
rs$.next(entry);
});
function wait(milliseconds: number) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
问题:
我到底做错了什么?
如果你想尝试一下:https://stackblitz.com/edit/rxjs-wpnqvq?file=index.ts
编辑1:
SetTimeout也没有任何作用。以下代码与上述代码完全相同:
fakeAPIValuesOne.forEach((value: number) => {
setTimeout(() => {
rs$.next(value);
}, 2000);
});
我想知道next()
如何覆盖这里的所有延迟?
编辑2
问题已解决,正确答案已标记,谢谢!您需要以下详细信息来运行根级别等待ts文件。
package.json
请注意类型部分:
{
"name": "playground",
"version": "1.0.0",
"description": "",
"main": "index.ts",
"scripts": {
"start": "nodemon index.ts",
"test": "echo "Error: no test specified" && exit 1"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"rxjs": "^7.5.5",
"ts-node": "^10.7.0",
"typescript": "^4.8.0-dev.20220507"
},
"type": "module"
}
nodemon.json
请考虑以下配置以避免错误:TypeError [ERR_UNKNOWN_FILE_EXTENSION]: Unknown file extension ".ts"
{
"execMap": {
"ts": "node --loader ts-node/esm"
}
}
最后但并非最不重要的tsconfig.json
{
"compilerOptions": {
"module": "ESNext",
"target": "ESNext",
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"isolatedModules": true,
"noEmit": true,
"strict": true,
"lib": ["esnext", "DOM"]
}
}
以下注释摘自此处的mozilla web文档
注意:
forEach
需要一个同步函数。
forEach
不等待承诺。确保您了解使用promise(或异步函数)作为forEach
时的含义回调。
所以这个问题与ReplaySubject
无关,只是不能将forEach
用于这个用例。
干杯
编辑:已解决
import { ReplaySubject } from "rxjs";
export const rs$ = new ReplaySubject();
rs$.subscribe({
next: (data) => console.log(data),
error: (error) => console.warn(error),
complete: () => console.log("ReplaySubject completed"),
});
const fakeAPIValuesOne = [7, 11, 13];
// That won't work:
// fakeAPIValuesOne.forEach(async (entry: number) => {
// await wait(2000);
// rs$.next(entry);
// });
// That will work
for (const element of fakeAPIValuesOne) {
await wait(2000);
rs$.next(element);
}
function wait(milliseconds: number) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
我认为值得一提的是,您不应该(通常)期望它起作用。
考虑以下内容:
wait(2000);
wait(2000);
wait(2000);
console.log("Hello");
"你好"将立即打印到控制台。不会等6秒钟。
如果你把它们放在一个循环中,这不会改变。
for (const n of [1,2,3]) {
wait(2000);
}
console.log("Hello");
这也将打印";你好"马上
如果不使用.then()
或await
,标准行为是不会等待。一些API(当然)会代表您执行等待,但预期的行为是它不会。
你需要这样写:
await wait(2000);
await wait(2000);
await wait(2000);
console.log("Hello");
现在您将等待6秒钟,然后再打印";你好"到控制台。
现在看看这个:
const createPromise = async (v) => {
await wait(2000);
console.log("Hello From createPromise: ", v);
}
createPromise(1);
createPromise(2);
createPromise(3);
console.log("Hello");
你会注意到这并没有什么不同。这将立即打印Hello,然后2秒后所有承诺都将解析并打印
Hello
// 2 seconds wait
Hello From createPromise: 1
Hello From createPromise: 2
Hello From createPromise: 3
你会注意到他们没有一个人在等着对方。这是承诺的预期行为。您需要使用await
或.then
才能实际等待承诺的结果。
你需要写:
await createPromise(1);
await createPromise(2);
await createPromise(3);
console.log("Hello");
这两个循环做相同的事情(正如预期的那样,它们不会等待)
for (const n of [1,2,3]) {
createPromise(n);
}
[1,2,3].forEach(n => createPromise(n))
console.log("Hello");
同样,您将看到打印的第一件事是"Hello"
,因为您永远不会等待这些承诺中的任何一个得到解决。
你确实在等待内心的wait(2000)
承诺,但你从不等待外在的createPromise()
承诺。所以你当然不会等他们:)
for (const n of [1,2,3]) {
await createPromise(n);
}