javascript有一个期约调用,就是利用内部的一种协程机制实现的类似并行的操作。以下是用ChatGPT搞出来的一块演示代码:
// 异步任务
function asyncTask() {
return new Promise((resolve, reject) => {
setTimeout(() => {
const randomNumber = Math.floor(Math.random() * 10);
if (randomNumber < 5) {
resolve(randomNumber);
} else {
reject("Error: Random number is greater than or equal to 5");
}
}, 1000);
});
}
// 调用异步任务
asyncTask()
.then((result) => {
console.log("Resolved:", result);
})
.catch((error) => {
console.error("Rejected:", error);
});
可以看到,这个里面用了asyncTask创建了一个期约,然后调用期约执行程序。在期约执行的期间主线程会继续执行。
下面有C++11搞了个类似的通过then串联逻辑链的:
template<typename f_t, typename...fs_t>
class chain
{
private:
f_t cur_f;
chain<fs_t...> next;
public:
chain(f_t f, fs_t...fs) :cur_f(f), next(fs...)
{
}
chain(f_t f, chain<fs_t...> pre):cur_f(f), next(pre)
{
}
template<typename next_f_t>
auto then(next_f_t next_f)
{
return chain<next_f_t, f_t, fs_t...>(next_f, *this);
}
template<typename...args_t>
auto run(args_t...args)
{
return cur_f(next.run(args...));
}
template<typename...args_t>
void start(args_t...args)
{
std::thread([&]() {run(args...); }).detach(); // 使用一种并行机制运行
}
};
template<typename f_t>
class chain<f_t>
{
private:
f_t cur_f;
public:
chain(f_t f):cur_f(f)
{}
template<typename next_f_t>
auto then(next_f_t next_f)
{
return chain<next_f_t, f_t>(next_f, cur_f);
}
template<typename...args_t>
auto run(args_t...args)
{
return cur_f(args...);
}
template<typename...args_t>
void start(args_t...args)
{
std::thread([&]() {run(args...); }).detach(); // 使用一种并行机制运行
}
};
template<typename f_t>
chain<f_t> chain_call(f_t f)
{
return chain<f_t>(f);
}
#include <iostream>
#include <future>
#include <chrono>
int main(int argc, char** argv)
{
chain_call([](int i) {return i + 1; })
.then([](int i) { return i * i; })
.then([](int i) {return i * (i + 1); })
.then([](int i) {std::cout << i << std::endl; })
.start(1);
std::this_thread::sleep_for(std::chrono::seconds(3));
std::cout << "main out" << std::endl;
return 0;
}
这个程序的原理就是通过chain_call的一元构造函数构造出来一个chain_call<f_t>的对象,然后调用then自动创建出chain_call<f_t,f_t1...>。实际最后调用start的是一个chain_call<f_t,f_t1...>的对象。
在boost中有一个叫signals2的模块,这个模块是设计用于观察者模式的,可以动态地注册槽函数(slot),最后形成一个调用链。signals2的调用链槽函数形式必须是统一的,这样信号对象在调用的时候可以把传入参数作为下面各个槽的参数,槽函数之间是没有直接关系的。而本博客实现的调用链上一个调用的返回结果作为下一个调用的参数,可以形成一个调用链,这样模块化更好一些。但是缺点也很明显,在构造的时候要构造chain_call<f_t>,chain_call<f_t,f_t1>...所有类型的对象,构造的代价比较大。