Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/date/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用资源序列化并发操作_Javascript_Async Await - Fatal编程技术网

Javascript 使用资源序列化并发操作

Javascript 使用资源序列化并发操作,javascript,async-await,Javascript,Async Await,我有一份手术单。每个操作使用一个资源。某些操作使用相同的资源。 例如,op1使用与op3相同的资源。 符号代码: operations=[op1,op2,op3,op4,op5] for (let i=0;i<operations.length;i++) { perform(operations[i]) } operations=[op1,op2,op3,op4,op5] 对于(设i=0;i你可以这样做 注意-这段代码可以用一种更优化的方式编写。这只是给你一个想法 let oper

我有一份手术单。每个操作使用一个资源。某些操作使用相同的资源。 例如,op1使用与op3相同的资源。 符号代码:

operations=[op1,op2,op3,op4,op5]
for (let i=0;i<operations.length;i++) {
  perform(operations[i])
}
operations=[op1,op2,op3,op4,op5]

对于(设i=0;i你可以这样做

注意-这段代码可以用一种更优化的方式编写。这只是给你一个想法

let operation=(操作,时间)=>()=>{
返回新承诺((解决、拒绝)=>{
设置超时(()=>{
解决();
},时间);
});
};
设op1=操作(“op1”,10000);
设op2=操作(“op2”,2000);
设op3=操作(“op3”,2000年);
设op4=操作(“op4”,1000);
设op5=操作(“op5”,5000);
常量运算=[
{名称:“op1”,操作:op1,资源:“R1”,起始地址:0},
{名称:“op2”,操作:op2,资源:“R2”,起始地址:0},
{名称:“op3”,操作:op3,资源:“R1”,起始地址:0},
{名称:“op4”,操作:op4,资源:“R4”,起始地址:0},
{名称:“op5”,操作:op5,资源:“R5”,起始地址:0}
];
让资源={
“R1”:{
是的,
队列:[]
},
“R2”:{
是的,
队列:[]
},
“R3”:{
是的,
队列:[]
},
“R4”:{
是的,
队列:[]
},
“R5”:{
是的,
队列:[]
},
};
异步函数操作执行器(操作){
if(operation.startedAt==0){
operation.startedAt=performance.now();
}
如果(!resources[operation.resource].isAvailable){
console.log(“Operation”、Operation.name、“等待资源”、Operation.Resource);
资源[operation.resource].queue.push(操作);
}否则{
console.log(“操作已启动”,操作名);
resources[operation.resource].isAvailable=false;
console.log(“资源锁定”,operation.Resource);
等待操作。操作();
常数t1=性能。现在();
console.log(“资源释放”,operation.Resource);
resources[operation.resource].isAvailable=true;
log(“操作完成”,Operation.name,`in${(t1-Operation.startedAt).toFixed(2)}毫秒`);
if(Array.isArray(resources[operation.resource].queue)和&resources[operation.resource].queue.length>0){
operationExecutor(资源[operation.resource].queue.splice(0,1)[0]);
}
}
}
for(设i=0;i}
鉴于这些操作不依赖于彼此的结果,您可以对每个资源创建并发队列,然后按顺序在每个资源中运行操作:

const opsByResource = new Map()
for (const op in operations) {
    const r = op.usedResource
    if (!opsByResource.has(r)) opsByResource.put(r, [])
    opsByResource.get(r).push(op)
}

return Promise.all(Array.from(opsByResource, async ([res, ops]) => {
    for (const op in ops)
        await perform(op)
    console.log("Done with all operations on", res)
}))

受您的解决方案启发,我采用以下方式:

  • 每个资源保持锁(承诺)队列
  • 在执行函数中,我从队列中弹出第一个锁,并在最后按下我的锁(承诺)
  • 然后等待第一个锁,执行操作并解决我的锁

我正在广泛使用我的受控承诺的实现,这是带有暴露的“resolveTo”的规范承诺函数,并具有指定超时后自动解析的选项。我想知道是否有人使用类似的东西,我个人无法想象没有它的编程。

创建一个待办事项列表。迭代整个列表,并在所有依赖项都可用的情况下启动所有操作(跟踪可用和使用的依赖项),然后从待办事项列表中删除这些项。任务完成后,使其使用的依赖项可用,然后再次遍历整个列表,并在所有依赖项可用的情况下启动所有操作,依此类推……这一次很可能只启动一个操作,但谁知道呢。单击并重复,直到odo列表是空的,没有任务正在运行。
异步函数中的
setTimeout
是怎么回事?第一个?我的意思是在第二个代码段中。我看不到
setTimeout(…,0)
的任何用法,一般来说,在promise代码中应该避免异步回调。(操作中的
中的回调很好)是的,
setTimeout(…,0)
不是必需的。我可以简单地调用它而无需等待,比如
operationExecutor(参考资料[operation.resource].queue.splice(0,1)[0]);
。这样当前操作的控制可以从operationExecutor函数中出来。如果我添加wait,则当前操作需要等待出来,直到队列清空。使用
承诺。所有
,如果任何操作失败。它将使所有其他独立操作失败。对吗?@Abhishek否,没有canc承诺中的细分。它只会使
promise.all
返回的结果承诺失败。当然,如果您对每个资源的单个结果感兴趣,您也可以使用
promise.allsolited
。或者您可能只想捕获单个循环迭代中的异常,并在失败后继续执行下一个操作或者别的什么。。。
operations=[op1,op2,op3,op4,op5]
for (let i=0;i<operations.length;i++) {
  await operations[i].usedResource.isAvailable;
  perform(operations[i])
}
const opsByResource = new Map()
for (const op in operations) {
    const r = op.usedResource
    if (!opsByResource.has(r)) opsByResource.put(r, [])
    opsByResource.get(r).push(op)
}

return Promise.all(Array.from(opsByResource, async ([res, ops]) => {
    for (const op in ops)
        await perform(op)
    console.log("Done with all operations on", res)
}))