Skip to content
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

1.多个Promise 串行调用 && 2.实现一个异步并发调度器 #35

Open
lizheng0515 opened this issue Jul 8, 2021 · 0 comments
Open
Labels
question Further information is requested

Comments

@lizheng0515
Copy link
Owner

lizheng0515 commented Jul 8, 2021

Promise 串行调用

怎么串行执行 Promise ?

这里简单给大家介绍下解答。针对多个 Promise 方法,原生提供了 allrace 方法。但是,他们都不是串行执行。那应该如果执行串行方法?

简单来说就是在 then 方法里面递归传递下一次异步方法:then(next())

function iteratorPromise(arr){

	(function iter(){
		if(arr.length){
                        // 取出第一项执行,.then()里递归调用执行下一项
			arr.shift()().then(iter)
                }
	})()
};

let arr = [
    ()=>{
	    return new Promise(res=>{
		    console.log("run", Date.now());
		    res()
	    })
    },
    ()=>{
	    return new Promise(res=>{
		    console.log("run", Date.now());
		    res()
	    })
    },
    ()=>{
	    return new Promise(res=>{
		    console.log("run", Date.now());
		    res()
	    })
    }
];

iteratorPromise(arr);

// output
run 1529918098567
run 1529918098568
run 1529918098569

实现一个异步并发调度器

//支持并发的调度器, 最多允许2两任务进行处理
const scheduler = new Scheduler(2)
scheduler.addTask(1, '1');   // 1s后输出’1'
scheduler.addTask(2, '2');  // 2s后输出’2'
scheduler.addTask(1, '3');  // 2s后输出’3'
scheduler.addTask(1, '4');  // 3s后输出’4'
scheduler.start();

以下的思路:

  1. 首先用一个maxCount记录允许并发的数量,用一个tasks数组保存所有开始之前设定的任务
  2. 我们需要对加入的任务进行一些封装,改成promise,这样就可以获取到完成的状态进行操作
  3. 我们用working数组保存正在运行的任务,用tasks保存还未完成的任务
  4. 在任务完成后,将tasks队列的第一个任务放入working中,并且运行
  5. 如此,通过递归,就可以完成一个并发控制器
// 异步调度器
class Scheduler {
    maxCount = 0
    tasks = []
    working = []
    constructor(count) {
        this.maxCount = count;
    }
    addTask = (timer, content) => {
        // 控制函数
        const target = () => {
            return new Promise((resolve) => {
                setTimeout(() => {
                    console.log(content);
                    resolve();
                }, 1000 * timer);
            })
        }
        // 入队列
        this.tasks.push(target)
    }
    continueWork = (fn) => {
        // 递归终点(执行完成)
        if (this.tasks.length > 0) {
            // 将后面的拿进来继续执行
            // 先确定下标
            let idx = -1;
            for (let i = 0; i < this.working.length; i++) {
                if (fn === this.working[i]) {
                    // 将其替换并执行
                    idx = i;
                    break;
                }
            }
            // 调用并运行
            const next = this.tasks.shift();
            next().then(() => {
                this.continueWork(next)
            })
            this.working[idx] = next;
        }
    }
    start = () => {
        let len = this.tasks.length;
        if (len >= this.maxCount) {
            // 否则就将其加入工作队列并执行
            this.working = this.tasks.splice(0, this.maxCount);
            console.log(this.working.length)
            this.working.map(fn => {
                fn().then(() => {
                    // 完成后再回调
                    // 当前执行完毕
                    this.continueWork(fn);
                })
            })
        } else {
            //小于调度范围: 直接全部执行
            this.tasks.map(fn => fn())
        }
    }
}

另一种实现方式:

class Scheduler {
            constructor(limit) {
                this.limit = limit
                this.number = 0
                this.queue = []
            }
            addTask(timeout, str) {
                this.queue.push([timeout, str])
            }
            start() {
                if (this.number < this.limit&&this.queue.length) {
                    var [timeout, str] = this.queue.shift()
                    this.number++
                    setTimeout(() => {
                        console.log(str)
                        this.number--
                        this.start()
                    }, timeout * 1000);
                    this.start()
                }
            }
 }
@lizheng0515 lizheng0515 changed the title 多个Promise 串行调用 多个Promise 串行调用 && 实现一个异步并发调度器 Jul 8, 2021
@lizheng0515 lizheng0515 added the question Further information is requested label Jul 8, 2021
@lizheng0515 lizheng0515 changed the title 多个Promise 串行调用 && 实现一个异步并发调度器 1.多个Promise 串行调用 && 2.实现一个异步并发调度器 Jul 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant