与js生成器进行2向通信的功能非常强大(请参阅here)。它启用了类似于基于CSP的编程语言中的通道的功能。
我似乎无法弄清楚如何使用异步生成器来做到这一点。假设我通过以下方式创建了一个异步生成器:
async function* asyncGenFn() {
yield Promise.resolve(true)
}
此函数返回AsyncIterableIterator
(而不是AsyncIterator
),它似乎不像next
那样具有IterablIterator
函数。
是否有一种方法可以与以此方式创建的异步生成器进行2通通信?还是我只是在这里树错树了?
答案 0 :(得分:2)
这是使用发电机进行双向通讯的示例-
const g = function* (x)
{ // yield sends a message "out"
// inbound message will be assigned to msg1
const msg1 = yield "sending this out"
// another outbound message
// inbound message will be assigned to msg2
const msg2 = yield "sending this too"
// do something
console.log(msg1, msg2)
// finally, return a value
// don't forget generators can accept arguments, like x here
return x * 2
}
// instantiate the generator
const iterator = g (100)
// get the first value from the iterator
let val = iterator.next()
// some example message to send to the generator
let m = 1
while (!val.done)
{ // log each outbound message
console.log("received message", val.value)
// .next resumes the generator and sends a message back "in"
val = iterator.next(m)
// increment the example message
m = m + 1
}
// display the final value
console.log("return value", val.value)
输出
received message sending this out
received message sending this too
1 2
return value 200
最好通过将2维通信应用于问题来学习2维通信。生成器赋予我们的这种暂停/恢复行为使它们非常适合处理异步操作。较新的async
和await
使我们能够模糊同步和异步代码之间的界限-
const delay = x =>
new Promise (r => setTimeout (r, 1e3, x))
const main = async (z) =>
{ const x = await delay (200) // some promise
const y = await delay (300) // some promise
return x + y + z // some computation with all the values
}
main (100) .then (console.log, console.error)
// 2 seconds later...
// => 600
但是在拥有async
和await
之前,我们已经有了生成器。下面是run
与发电机的双向通讯的一个很好的演示。除了使用生成器函数和yield
表达式-
const delay = x =>
new Promise (r => setTimeout (r, 1e3, x))
const main = function* (z)
{ const x = yield delay (200) // some promise
const y = yield delay (300) // some promise
return x + y + z // some computation with all the values
}
const run = it =>
{ const loop = ({ done, value }) =>
done
? Promise .resolve (value)
: value .then (x => loop (it .next (x)))
return loop (it .next ())
}
run (main (100)) .then (console.log, console.error)
// 2 seconds later...
// => 600
以上,run
被实现为一个简单的递归函数,该函数接受生成器的出站承诺并将承诺的已解析值发送回生成器。它会一直执行到生成器用尽并解析出最终值-
const run = it =>
{ const loop = ({ done, value }) =>
// if the iterator is done
done
// resolve the final value
? Promise .resolve (value)
// otherwise resolve the value, send it back into the generator, recur
: value .then (x => loop (it .next (x)))
// initialize the loop with the first value
return loop (it .next ())
}
在使用生成器模拟协程之前,我们被困在手动编写代码的过程中,方法是在代码中手动链接.then
调用-
const delay = x =>
new Promise (r => setTimeout (r, 1e3, x))
const main = z =>
delay (200) .then (x => // manually chain then
delay (300) .then (y => // manually chain then
x + y + z // some computation with all the values
)) // close each then
main (100) .then (console.log, console.error)
// 2 seconds later...
// => 600
如您所见,与生成器的2通通信功能强大,可为我们提供复杂程序的漂亮表达。 JavaScript添加了async
/ await
关键字,这些关键字可能看起来像魔术,但是run
使您了解了如何使用双向通信来获得相同的行为,即使没有新关键字。
答案 1 :(得分:1)
这是我最后一个与Typescript编译选项有关的问题。在我的def startClicking():
jsScript = open('clicks.js', 'r')
jsScriptContent = jsScript.read()
time.sleep(2)
driver.execute_script(jsScriptContent)
time.sleep(1)
jsScript.close()
中添加以下内容为我解决了这个问题:
tsconfig.json
感谢大家参观!