Javascript 等待flag=true

Javascript 等待flag=true,javascript,synchronization,Javascript,Synchronization,我有如下javascript函数: function myFunction(number) { var x=number; ... ... more initializations //here need to wait until flag==true while(flag==false) {} ... ... do something } 问题是javascript卡在了while中,卡在了我的程序中。因此,我的问题是,

我有如下javascript函数:

function myFunction(number) {

    var x=number;
    ...
    ... more initializations
    //here need to wait until flag==true
    while(flag==false)
    {}

    ...
    ... do something

}

问题是javascript卡在了while中,卡在了我的程序中。因此,我的问题是,如何在函数中间等待,直到没有“忙等待”的标志是真的?

< P> JavaScript是单线程的,因此页面阻塞行为。您可以使用其他人建议的延迟/承诺方法,但最基本的方法是使用
window.setTimeout
。例如

function checkFlag() {
    if(flag == false) {
       window.setTimeout(checkFlag, 100); /* this checks the flag every 100 milliseconds*/
    } else {
      /* do something*/
    }
}
checkFlag();
下面是一个很好的教程,有进一步的解释:

编辑


正如其他人指出的,最好的方法是重新构造代码以使用回调。但是,这个答案应该让您了解如何使用
window.setTimeout
来“模拟”异步行为

由于浏览器中的javascript是单线程的(此处不涉及的webworkers除外),并且javascript执行的一个线程在另一个线程运行之前一直运行到完成,因此您的语句:

while(flag==false) {}
将永远运行(或者直到浏览器抱怨没有响应的javascript循环),页面将显示为挂起,并且没有其他javascript有机会运行,因此标志的值永远不会更改

再解释一下,Javascript是一种事件驱动语言。这意味着它运行一段Javascript,直到将控制权返回给解释器为止。然后,只有当它返回到解释器时,Javascript才会从事件队列中获取下一个事件并运行它

计时器和网络事件等所有内容都会在事件队列中运行。因此,当计时器启动或网络请求到达时,它不会“中断”当前运行的Javascript。相反,一个事件被放入Javascript事件队列,然后,当当前运行的Javascript完成时,下一个事件被从事件队列中拉出来,轮到它运行

因此,当您执行无限循环(例如
while(flag==false){}
)时,当前运行的Javascript永远不会完成,因此下一个事件永远不会从事件队列中提取,因此
flag
的值永远不会更改。这里的关键是Javascript不是中断驱动的。当计时器启动时,它不会中断当前运行的Javascript,而是运行一些其他Javascript,然后让当前运行的Javascript继续。它只是被放在事件队列中,等待当前运行的Javascript完成,以轮到它运行


您需要做的是重新思考代码的工作方式,并找到一种不同的方式,在
标志
值更改时触发您想要运行的任何代码。Javascript被设计为一种事件驱动语言。所以您需要做的是找出您可以注册感兴趣的事件,以便您可以侦听可能导致标志更改的事件并检查该事件上的标志,或者您可以从任何可能更改标志的代码触发您自己的事件,或者您可以实现任何更改该标志的代码的回调函数只要负责更改标志值的代码段将其值更改为
true
,它就可以调用回调函数,因此当标志设置为
true
时要运行的代码将在正确的时间运行。这比尝试使用某种计时器来不断检查标志值要有效得多

function codeThatMightChangeFlag(callback) {
    // do a bunch of stuff
    if (condition happens to change flag value) {
        // call the callback to notify other code
        callback();
    }
}
要迭代($.each)对象并对每个对象执行长时间运行操作(包含嵌套的ajax同步调用),请执行以下操作:

我首先在每个属性上设置一个自定义
done=false
属性

然后,在递归函数中,设置每个
done=true
,并继续使用
setTimeout
。(这是一项旨在停止所有其他UI、显示进度条和阻止所有其他使用的操作,因此我原谅了自己的同步调用。)

使用:


使用Ecma脚本2017,您可以使用async await和while来完成此任务 而while将不会崩溃或锁定程序,即使变量永远不会为真

//首先定义一些从异步函数调用的延迟函数
功能延迟(计时器){
返回新承诺(解决=>{
定时器=定时器| | 2000;
setTimeout(函数(){
解决();
},定时器);
});
};
//然后声明某个变量为全局变量或范围内变量
//全靠你了
var标志=假;
//定义你想要的异步功能
异步函数some(){
while(!flag)
等待延迟(1000);
//…在此处编码,因为当Variable=true时,此函数将
};
//函数a(回调){
setTimeout(函数(){
console.log(“你好,我是订单1”);
}, 3000);
//回调();
//}
//函数b(回调){
setTimeout(函数(){
console.log('Hi I am order 2');
}, 2000);
//回调();
//}
//函数c(回调){
setTimeout(函数(){
console.log('Hi I am order 3');
}, 1000);
//回调();
//}
/*函数d(回调){
a(函数(){
b(职能({
c(回调);
});
});
}
d()*/
异步函数funa(){
var pr1=新承诺((res,rej)=>{
setTimeout(()=>res(“Hi4我是订单1”),3000)
})
var pr2=新承诺((res,rej)=>{
setTimeout(()=>res(“Hi4我是订单2”),2000)
})
var pr3=新承诺((res,rej)=>{
setTimeout(()=>res(“Hi4我是订单3”),1000)
})
var res1=等待pr1;
var res2=等待pr2;
var res3=等待pr3;
console.log(res1、res2、res3);
控制台日志(res1);
console.log(res2);
控制台日志(res3);
}   
funa();
异步函数f1(){
等待新的承诺(r=>setTimeout(r,3000))
.然后(()=>console.log('Hi3我是订单1'))
返回1;
}
异步函数f2(){
等待新的承诺(r=>setTimeout(r,2000))
.然后(()=>console.log('Hi3我是订单2'))
返回2;
function start()
{
    GlobalProducts = getproductsfromsomewhere();
    $.each(GlobalProducts, function(index, product) {
         product["done"] = false;
    });

    DoProducts();
}
function DoProducts()
{
    var doneProducts = Enumerable.From(GlobalProducts).Where("$.done == true").ToArray(); //linqjs

    //update progress bar here

    var nextProduct = Enumerable.From(GlobalProducts).Where("$.done == false").First();

        if (nextProduct) {
            nextProduct.done = true;
            Me.UploadProduct(nextProduct.id); //does the long-running work

            setTimeout(Me.UpdateProducts, 500)
        }
}
function waitFor(condition, callback) {
    if(!condition()) {
        console.log('waiting');
        window.setTimeout(waitFor.bind(null, condition, callback), 100); /* this checks the flag every 100 milliseconds*/
    } else {
        console.log('done');
        callback();
    }
}
waitFor(() => window.waitForMe, () => console.log('got you'))
let meaningOfLife = false;
async function waitForMeaningOfLife(){
   while (true){
        if (meaningOfLife) { console.log(42); return };
        await null; // prevents app from hanging
   }
}
waitForMeaningOfLife();
setTimeout(()=>meaningOfLife=true,420)
async function myFunction(number) {

    var x=number;
    ...
    ... more initializations

    await until(_ => flag == true);

    ...
    ... do something

}
function until(conditionFunction) {

  const poll = resolve => {
    if(conditionFunction()) resolve();
    else setTimeout(_ => poll(resolve), 400);
  }

  return new Promise(poll);
}
const EventEmitter = require('events');

const bus = new EventEmitter();
let lock = false;

async function lockable() {
    if (lock) await new Promise(resolve => bus.once('unlocked', resolve));
    ....
    lock = true;
    ...some logic....
    lock = false;
    bus.emit('unlocked');
}
function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
}

async function until(fn) {
    while (!fn()) {
        await sleep(0)
    }
}

async function myFunction(number) {
    let x = number
    ...
    ... more initialization

    await until(() => flag == true)

    ...
    ... do something
}
checkFlag: function() {
  var currentObject = this; 
  if(flag == false) {
      setTimeout(currentObject.checkFlag, 100); 
   } else {
     /* do something*/
   }
}
checkFlag: function() {
    var worker = setInterval (function(){
         if(flag == true){             
             /* do something*/
              clearInterval (worker);
         } 
    },100);
 }
const delay = require('delay');

(async () => {
    bar();

    await delay(100);

    // Executed 100 milliseconds later
    baz();
})();
const waitFor = async (condFunc: () => boolean) => {
  return new Promise((resolve) => {
    if (condFunc()) {
      resolve();
    }
    else {
      setTimeout(async () => {
        await waitFor(condFunc);
        resolve();
      }, 100);
    }
  });
};

const myFunc = async () => {
  await waitFor(() => (window as any).goahead === true);
  console.log('hello world');
};

myFunc();
let _queue = [];

const _addToQueue = (funcToQ) => {
    _queue.push(funcToQ);
}
const _runQueue = () => {
    if (!_queue || !_queue.length) {
        return;
    }

    _queue.forEach(queuedFunc => {
        queuedFunc();
    });

    _queue = [];
}
_addToQueue(() => methodYouWantToCallLater(<pass any args here like you normally would>));
const waitUntil = (condition) => {
    return new Promise((resolve) => {
        let interval = setInterval(() => {
            if (!condition()) {
                return
            }

            clearInterval(interval)
            resolve()
        }, 100)
    })
}
await waitUntil(() => /* your condition */)
function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve();
    }, 2000);
  });
}




function myFunction(number) {

    var x=number;
    ...
    ... more initializations
    //here need to wait until flag==true
    while(flag==false)
    {
         await resolveAfter2Seconds();
    }

    ...
    ... do something

}