-
Notifications
You must be signed in to change notification settings - Fork 634
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
阿里异步串行编程题:按照以下要求,实现 createFlow 函数 #106
Labels
Comments
在本题中,
() => console.log("a")
() => delay(1000).then(() => console.log("c"))
const subFlow = createFlow([() => delay(1000).then(() => console.log("c"))])
[() => delay(1000).then(() => console.log("d")), () => console.log("e")] 步骤一:扁平化因为 function createFlow(effects = []) {
// 浅拷贝一下,今年不影响传入的参数
const queue = [...effects.flat()]
} 步骤二:run执行
function createFlow(effects = []) {
const queue = [...effects.flat()]
const run = async function(cb) {
for(let task of queue) {
}
if(cb) cb()
}
} 步骤三:异步函数因为参数中有异步函数,这里使用 function createFlow(effects = []) {
const queue = [...effects.flat()]
const run = async function(cb) {
for(let task of queue) {
await task()
}
if(cb) cb()
}
} 步骤四:支持嵌套使用 function createFlow(effects = []) {
const queue = [...effects.flat()]
const run = async function(cb) {
for(let task of queue) {
if(task.isFlow) { // 如果是嵌套,执行嵌套函数
await task.run()
} else {
await task()
}
}
if(cb) cb()
}
return {
run,
isFlow: true
}
} 其实是可以使用 class Flow {
constructor(props) {
this.queue = props
}
async run(cb) {
for(let task of this.queue) {
if(task instanceof Flow) {
await task.run()
} else {
await task()
}
}
if(cb) cb()
}
}
function createFlow(effects = []) {
return new Flow(effects)
} 完整代码:两种
function createFlow(effects = []) {
const queue = [...effects.flat()]
const run = async function(cb) {
for(let task of queue) {
if(task.isFlow) {
await task.run()
} else {
await task()
}
}
if(cb) cb()
}
return {
run,
isFlow: true
}
}
// 测试
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const subFlow = createFlow([() => delay(1000).then(() => console.log("c"))]);
createFlow([
() => console.log("a"),
() => console.log("b"),
subFlow,
[() => delay(1000).then(() => console.log("d")), () => console.log("e")],
]).run(() => {
console.log("done");
});
// a,b,延迟1秒,c,延迟1秒,d,e, done 的顺序打印
class Flow {
constructor(effects) {
this.queue = [...effects.flat()]
}
async run(cb) {
for(let task of this.queue) {
if(task instanceof Flow) {
await task.run()
} else {
await task()
}
}
if(cb) cb()
}
};
function createFlow(effects = []) {
return new Flow(effects)
};
// 测试
const delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
const subFlow = createFlow([() => delay(1000).then(() => console.log("c"))]);
createFlow([
() => console.log("a"),
() => console.log("b"),
subFlow,
[() => delay(1000).then(() => console.log("d")), () => console.log("e")],
]).run(() => {
console.log("done");
});
// a,b,延迟1秒,c,延迟1秒,d,e, done 的顺序打印 |
const createFlow = (lists) => {
return new Promise((re, rj) => {
let i=0
let len = lists.length
const next = (i)=>{
if(i == lists.length) return re()
let item = lists[i]
if(Array.isArray(item)) {
createFlow(item).then(() => next(i+1))
}else if(item instanceof Promise) {
Promise.resolve(item).then(() => next(i+1))
}else if(typeof item == 'function') {
let res = item()
if(res instanceof Promise){
Promise.resolve(res).then(() =>next(i+1))
}else{
next(i+1)
}
}else {
next(i+1)
}
}
next(i)
})
}
Promise.prototype.run = function(cb) {
this.then(cb)
}
const delay = ms => new Promise(re => setTimeout(re, ms))
const subFlow = createFlow([() => delay(1000).then(() => console.log('c'))])
createFlow([
() => console.log('a'),
() => console.log('b'),
subFlow,
[() => delay(1000).then(() => console.log('d')), () => console.log('e')],
]).run(() => console.log('done')) |
之前会错意了,思路一样,利用 Promise 异步串行 const createFlow = (lists) => {
let tasks = [...lists].flat()
const run = (cb) => {
let [first, ...others] = [...tasks]
return others.reduce((promise, task) => {
task = task.run ? task.run : task
return Promise.resolve(promise).then(_ => task())
}, first()).then(cb)
}
return { run }
} |
其实我还有一个思路:
function isType(target, type) {
return (Object.prototype.toString.call(target) || '').indexOf(type) > -1;
}
function log(msg) {
return console.log(msg);
}
function createFlow(arr) {
let task = [];
arr.forEach(item => {
if (isType(item, 'Function')) {
if (item.name === 'createFlow') {
task = task.concat(item.task);
} else {
task.push(item);
}
}
if (isType(item, 'Array')) {
task = task.concat(item);
}
})
createFlow.task = task;
createFlow.run = function (fn) {
if (this.task.length > 0) {
const func = task.shift();
const result = func();
// 这里判断
if (result && typeof result.then === 'function') {
result.then(() => this.run(fn));
} else {
this.run(fn);
}
} else {
typeof fn === 'function' && fn();
}
}
return createFlow;
} |
function createFlow(arr) {
let curList = [];
add(arr);
return {
run: function (cb) {
if(cb){
curList.push(cb);
}
go(curList);
},
_list: curList
}
async function go(list) {
for(let i = 0;i<list.length;i++){
await list[i]();
}
}
function add(list) {
for(let i = 0;i<list.length;i++){
let item = list[i];
if(typeof item === 'function'){
curList.push(item)
}
if(Array.isArray(item)){
add(item)
}
if(typeof item === 'object' && item._list){
add(item._list)
}
}
}
} |
function createFlow(arr){
arr.run = async (cb) => {
for(let fn of arr.flat(99)){
await fn()
}
cb && cb()
}
return arr
} |
不简洁但是把步骤拆分成了collect和run两个阶段,不进行flat class Flow {
constructor(task) {
this.task = task
}
async run(cb) {
await this.task()
cb instanceof Function && cb()
}
}
const runFlow = async (flow) => {
if (flow instanceof Array) {
for (const item of flow) {
await runFlow(item)
}
} else if (flow instanceof Function) {
await runFlow(flow())
} else if (flow instanceof Flow) {
await flow.run()
} else if (flow instanceof Promise) {
await flow
} else {
// static val, do nothing
return
}
}
const collectFlow = (flow, list = []) => {
list.push(() => runFlow(flow))
return list
}
export const createFlow = (flow) => {
return new Flow(() => runFlow(collectFlow(flow, [])))
} |
type Effect = (() => Promise<void> | void) | Flow;
class Flow {
private _queue: (() => void)[];
private _endCallback: (() => void) | undefined;
constructor(effects: Effect[]) {
this._queue = effects.map((effect) => {
const fn = () => {
Promise.resolve(effect instanceof Flow ? effect.run() : effect()).finally(() => {
this._next();
});
};
return fn;
});
}
private _next() {
const fn = this._queue.shift();
if (fn) {
fn();
} else if (this._endCallback) {
this._endCallback();
}
}
public run(callback?: () => void): void {
this._endCallback = callback;
this._next();
}
}
function createFlow(effects: (Effect | Effect[])[]) {
return new Flow(effects.flat());
}
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
const subFlow = createFlow([() => delay(1000).then(() => console.log("c"))]);
createFlow([
() => console.log("a"),
() => console.log("b"),
subFlow,
[() => delay(1000).then(() => console.log("d")), () => console.log("e")],
]).run(() => {
console.log("done");
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
按照上面的测试用例,实现
createFlow
:flow
是指一系列effects
组成的逻辑片段。flow
支持嵌套。effects
的执行只需要支持串行。The text was updated successfully, but these errors were encountered: