【问题标题】:Wait and don't execute a function until a light is set to green等待并且在灯设置为绿色之前不要执行功能
【发布时间】:2017-08-02 19:07:07
【问题描述】:

我知道我们可以使用.then 来确定异步调用的顺序:

return doTask1()
    .then(function () {
        return doTask2()
    })

但有时有灯会很方便,并且可以说:等到灯设置为绿色后才执行task2; light 是一个初始设置为 RED 的变量,可以通过 task1 或其他函数设置为 GREEN。

有谁知道是否可以做到这一点?

编辑1:我认为当我们需要结束几个任务来设置浅绿色,并且我们不知道/介意顺序时,能够表达这一点特别有用这些任务.then 不能轻易做到这一点,因为我们不知道这些任务的顺序。

编辑 2: 关于my light,我曾问过a more specific question。总之,我们正在等待的是另一个应用程序 B 通过postMessage 发送的消息。目前,我已经编写了以下代码(在resolve 中),它或多或少都可以工作(我还没有尝试过只用它们的公共部分制作一个函数是否可以工作)。

task1: ['codeService', '$window', '$q', function (codeService, $window, $q) {
    return codeService.task1().then(function () { // task1 sends a request to another application B by postMessage
        var deferred = $q.defer();
        $window.addEventListener("message", function (event) {
            if (event.data.req === "task1ReturnFromB") deferred.resolve(event.data)
        }, { once: true });
        return deferred.promise
    })
}],
task2: ['codeService', 'task1', '$window', '$q', function(codeService, task1, $window, $q) {
    return codeService.task2().then(function () { // task2 sends a request to Application B by postMessage
        var deferred = $q.defer();
        $window.addEventListener("message", function (event) {
            if (event.data.req === "task2ReturnFromB") deferred.resolve(event.data) 
        }, { once: true });
        return deferred.promise
    })
}]

所以在这种特定情况下,应用程序 B 发送的postMessage 会触发该事件。在更一般的情况下,我想我们可能会在一个应用程序中通过例如dispatchEvent 触发一个事件?

【问题讨论】:

  • 您需要定义一个事件处理程序 - 例如function onGreenLight(),然后在设置灯光颜色的部分代码中执行它。这不是异步或同步的——这是事件驱动的。您无需等待它变绿 - 当它变绿时您就可以做一些事情。
  • onGreenLight可以通过doTask1()等函数结束触发。在 JavaScript 中触发事件的最佳方式是什么?
  • 将灯设置为红色或绿色的代码 - 您在此处执行事件处理程序。
  • @SoftTimur 最好不要混合和匹配异步模型。使用代表灯变绿的承诺,并在其上使用then(或将其与其他一些承诺结合使用)。
  • 你没有告诉我们你的灯是如何工作的(除了它不能做什么)。它提供了哪些 API?

标签: javascript asynchronous promise angular-promise


【解决方案1】:

你没有告诉我们任何关于你的灯的 API,所以我只能猜测它是什么样的。假设它是一个事件驱动模型,您可以将其转换为一个 Promise,然后执行以下操作:

function waitForGreenLight() {
    return new Promise(function (resolve) {
        $window.addEventListener("message", function (event) {
           if (event.data.req === "task2ReturnFromB") {
               resolve(event.data) 
           }
        }, { once: true });
    });
}

return doTask1()
    .then(waitForGreenLight)
    .then(doTask2);

如果您的灯不提供事件,您可以使用waitForGreenLight 定期轮询它,直到它变为绿色。使用waitForGreenLight 的代码将保持不变。

function waitForGreenLight() {
    return new Promise(function (resolve) {
        var handle = setInterval(function () { 
            if (myLight.color === 'green') { 
                resolve();
                clearInterval(handle);
            }
        }, 100);
    });
}

【讨论】:

  • 谢谢...我认为不可能...您能否提供一个提供事件的灯光代码,以便完成第一个示例?
  • @SoftTimur 听起来您要问的内容超出了此问题的范围,即等待灯变绿。如果您想将您的灯光包装在基于事件的 API 中,请提出一个单独的问题。正如我已经两次指出的那样,你没有告诉我们任何关于你的灯的 API 是如何工作的。在向我询问更多代码之前,请提供我向您询问的信息。没有那个,我就帮不了你了。
  • 请看我的更新...我猜,在一般情况下,您的代码中的lightHandler 可能是$windowdocument 等。我们可以通过@987654328 触发事件@...对吗?
  • @SoftTimur 非常感谢。你能看看我的第一个样本的编辑版本吗?
【解决方案2】:

使用 Promise 是最好的方法。 Promise 是执行函数的对象,当该函数完成时,THEN 函数被执行。 但仅当函数返回结果时。

示例

var task1 = new Promise(function(resolve, reject) {
     var value = 1;
     setTimeout(function(){
          resolve(value);
     }, 1000);

});

var task1.then(function(value){
     // After one second, do something with your value here
});

【讨论】:

    猜你喜欢
    • 2020-01-15
    • 1970-01-01
    • 2015-06-02
    • 2020-08-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-05
    • 2020-12-24
    相关资源
    最近更新 更多