如何从 setTimeout 做出承诺

2023-11-30

这不是一个现实世界的问题,我只是想了解如何创建承诺。

我需要了解如何对不返回任何内容的函数做出承诺,例如 setTimeout。

假设我有:

function async(callback){ 
    setTimeout(function(){
        callback();
    }, 5000);
}

async(function(){
    console.log('async called back');
});

我如何创建一个承诺async后可返回setTimeout准备好callback()?

我以为包装它会带我去某个地方:

function setTimeoutReturnPromise(){

    function promise(){}

    promise.prototype.then = function() {
        console.log('timed out');
    };

    setTimeout(function(){
        return ???
    },2000);


    return promise;
}

但我无法思考除此之外的事情。


更新(2017)

2017 年,Promises 内置于 JavaScript 中,它们是由 ES2015 规范添加的(polyfills 可用于过时的环境,如 IE8-IE11)。他们使用的语法使用您传递到的回调Promise构造函数(Promise executor)它接收解析/拒绝承诺的函数作为参数。

首先,自从async现在在 JavaScript 中具有意义(即使它在某些情况下只是一个关键字),我将使用later作为函数的名称以避免混淆。

基本延迟

使用原生 Promise(或忠实的 Polyfill),它看起来像这样:

function later(delay) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay);
    });
}

请注意,这假设版本为setTimeout符合浏览器的定义 where setTimeout不会将任何参数传递给回调,除非您在时间间隔后给出它们(这在非浏览器环境中可能不是这样,并且过去在 Firefox 上不是这样,但现在是这样;在 Chrome 上甚至是后面也是这样在 IE8 上)。

基本延迟与价值

如果您希望您的函数可以选择传递分辨率值,则在任何允许您提供额外参数的模糊现代浏览器上setTimeout延迟后,然后在调用时将它们传递给回调,您可以执行此操作(当前的 Firefox 和 Chrome;IE11+,大概是 Edge;notIE8 或 IE9,不知道 IE10):

function later(delay, value) {
    return new Promise(function(resolve) {
        setTimeout(resolve, delay, value); // Note the order, `delay` before `value`
        /* Or for outdated browsers that don't support doing that:
        setTimeout(function() {
            resolve(value);
        }, delay);
        Or alternately:
        setTimeout(resolve.bind(null, value), delay);
        */
    });
}

如果您使用 ES2015+ 箭头函数,则可以更简洁:

function later(delay, value) {
    return new Promise(resolve => setTimeout(resolve, delay, value));
}

or even

const later = (delay, value) =>
    new Promise(resolve => setTimeout(resolve, delay, value));

可取消的延误(含价值)

如果你想让取消超时成为可能,你不能只返回一个承诺later,因为承诺无法取消。

但是我们可以轻松地返回一个对象cancel方法和 Promise 的访问器,并在取消时拒绝 Promise:

const later = (delay, value) => {
    let timer = 0;
    let reject = null;
    const promise = new Promise((resolve, _reject) => {
        reject = _reject;
        timer = setTimeout(resolve, delay, value);
    });
    return {
        get promise() { return promise; },
        cancel() {
            if (timer) {
                clearTimeout(timer);
                timer = 0;
                reject();
                reject = null;
            }
        }
    };
};

实例:

const later = (delay, value) => {
    let timer = 0;
    let reject = null;
    const promise = new Promise((resolve, _reject) => {
        reject = _reject;
        timer = setTimeout(resolve, delay, value);
    });
    return {
        get promise() { return promise; },
        cancel() {
            if (timer) {
                clearTimeout(timer);
                timer = 0;
                reject();
                reject = null;
            }
        }
    };
};

const l1 = later(100, "l1");
l1.promise
  .then(msg => { console.log(msg); })
  .catch(() => { console.log("l1 cancelled"); });

const l2 = later(200, "l2");
l2.promise
  .then(msg => { console.log(msg); })
  .catch(() => { console.log("l2 cancelled"); });
setTimeout(() => {
  l2.cancel();
}, 150);

2014年的原始答案

通常你会有一个承诺库(你自己编写的库,或者现有的几个库之一)。该库通常会有一个您可以创建并稍后“解析”的对象,并且该对象将有一个您可以从中获得的“承诺”。

Then later往往看起来像这样:

function later() {
    var p = new PromiseThingy();
    setTimeout(function() {
        p.resolve();
    }, 2000);

    return p.promise(); // Note we're not returning `p` directly
}

在对该问题的评论中,我问:

您是否想创建自己的承诺库?

你说

我不是,但我想现在这实际上就是我想要理解的。图书馆会如何做到这一点

为了帮助理解,这里有一个非常非常基本例如,它远程不符合 Promises-A:实时复制

<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>Very basic promises</title>
</head>
<body>
  <script>
    (function() {

      // ==== Very basic promise implementation, not remotely Promises-A compliant, just a very basic example
      var PromiseThingy = (function() {

        // Internal - trigger a callback
        function triggerCallback(callback, promise) {
          try {
            callback(promise.resolvedValue);
          }
          catch (e) {
          }
        }

        // The internal promise constructor, we don't share this
        function Promise() {
          this.callbacks = [];
        }

        // Register a 'then' callback
        Promise.prototype.then = function(callback) {
          var thispromise = this;

          if (!this.resolved) {
            // Not resolved yet, remember the callback
            this.callbacks.push(callback);
          }
          else {
            // Resolved; trigger callback right away, but always async
            setTimeout(function() {
              triggerCallback(callback, thispromise);
            }, 0);
          }
          return this;
        };

        // Our public constructor for PromiseThingys
        function PromiseThingy() {
          this.p = new Promise();
        }

        // Resolve our underlying promise
        PromiseThingy.prototype.resolve = function(value) {
          var n;

          if (!this.p.resolved) {
            this.p.resolved = true;
            this.p.resolvedValue = value;
            for (n = 0; n < this.p.callbacks.length; ++n) {
              triggerCallback(this.p.callbacks[n], this.p);
            }
          }
        };

        // Get our underlying promise
        PromiseThingy.prototype.promise = function() {
          return this.p;
        };

        // Export public
        return PromiseThingy;
      })();

      // ==== Using it

      function later() {
        var p = new PromiseThingy();
        setTimeout(function() {
          p.resolve();
        }, 2000);

        return p.promise(); // Note we're not returning `p` directly
      }

      display("Start " + Date.now());
      later().then(function() {
        display("Done1 " + Date.now());
      }).then(function() {
        display("Done2 " + Date.now());
      });

      function display(msg) {
        var p = document.createElement('p');
        p.innerHTML = String(msg);
        document.body.appendChild(p);
      }
    })();
  </script>
</body>
</html>
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 setTimeout 做出承诺 的相关文章

  • 有没有办法从 PhantomJS 的键盘读取用户输入?

    我使用 PhantomJS 登录网站 必须手动输入验证码 如何将验证码图像保存到磁盘 然后在 PhantomJS 控制台中手动输入验证码 我遇到了同样的问题 只需将系统模块与 page render 和一些传递给 page evaluate
  • JavaScript CSV 验证

    如何检查文本框中的逗号分隔值并在未找到时发出警报 如果有的话 里面应该有字符 比如A B C D function validate validate text box
  • 获取 CRM 2011 中功能区按钮的 ID

    我创建了一个 JavaScript 我想在其中隐藏功能区Reactivate Lead按钮取决于某些条件 我通过在表单上按 F12 获得了按钮的 ID 即lead NoRelationship Form Mscrm Form lead Re
  • 如何从 javascript 错误对象读取错误消息

    有人可以帮我解决以下问题吗 我正在通过 redux 操作进行后调用 如下所示 export const addEmployee firstName surname contactNumber email gt async dispatch
  • Javascript:使用 IIFE 和块语句之间的区别

    IIFE主要用于封装作用域 function let myVar 10 not global 但为什么不直接使用块语句呢 let myVar 10 also not global 除了范围封装之外 进一步使用 IIFE 是否还有其他好处 块
  • html 图像 src 调用 javaScript 变量

    这是我的代码 我想问 我怎样才能做到这一点 img src img apple 我一直在尝试使用 call 函数和 document onload 但它根本不起作用 有人可以救我吗 我假设你只是想用 javascript 更新图像 src
  • tomcat 7.0.50 java websocket 实现给出 404 错误

    我正在尝试使用 Java Websocket API 1 0 JSR 356 中指定的带注释端点在 tomcat 7 0 50 上实现 websocket 以下是我如何对其进行编码的简要步骤 1 使用 ServerEndpoint注解编写w
  • vuejs 模板和 asp.net 部分视图,好的做法吗?

    我在网站中使用 Vue js 并将模板添加到 html 代码中 并将 js 代码添加到单个 js 文件中 所以我不想使用 vue Vuefy Browserfy 方法 而是稍后捆绑并缩小我的 js 文件 由于我必须使用 Asp Net MV
  • 如何将本地文本文件上传到文本区域(网页内)

    我是一名新手程序员 需要一些帮助来弄清楚如何将本地文本文件上传到我正在构建的网站内的文本区域 我非常精通 HTML CSS 对 Javascript JQuery 有相当的了解 而且我刚刚学习 PHP 您能提供的任何帮助我将不胜感激 我有一
  • 只保留 A-Z 0-9 并使用 javascript 从字符串中删除其他字符

    我正在尝试验证字符串以使它们成为有效的网址 我只需要保留 A Z 0 9 并使用以下命令从字符串中删除其他字符javascript or jquery 例如 贝儿餐厅 我需要将其转换为 百丽餐厅 所以字符被删除 只保留 A Z a z 0
  • 我应该如何实现将状态保存到 localStorage?

    CODE var React require react var Recipe require Recipe jsx var AddRecipe require AddRecipe jsx var EditRecipe require Ed
  • 使用 Javascript/Node.js 在代码内执行 mongoimport

    node js javascript 中是否有任何库可供个人使用mongoimport在代码中 据我了解 mongoimport 有点像 exe 您必须先执行它 然后才能使用其文本输入环境 是否可以在我的代码中执行 mongoimport
  • 使用 JavaScript 防止网页导航离开

    如何使用 JavaScript 防止网页导航离开 Using onunload允许您显示消息 但不会中断导航 因为为时已晚 然而 使用onbeforeunload将中断导航 window onbeforeunload function re
  • ES6 静态方法引用 self? [复制]

    这个问题在这里已经有答案了 我有两节课 存储库和用户存储库 我想在 Repository 中定义一个静态方法 该方法在运行时调用 UserRepository 中的静态函数 有什么干净的方法可以做到这一点吗 class Repository
  • 如何使用 NextJS 使用自托管字体face?

    使用 NextJS 的字体 我已经阅读了有关如何在 NextJS 中使用自托管字体的不同主题 我得到了什么 wait compiling 当我这样做时 font face font family montserrat src url myp
  • 此版本的 CLI 仅与 Angular 版本 5.0.0 或更高版本兼容错误

    我已经有 Angular 项目在 4 版本中运行 在安装新项目时 不幸的是我安装了 6 版本的 Angular cli 在以 4 版本运行的旧项目中运行 ngserve 命令时 这会引发错误 您的全局 Angular CLI 版本大于本地版
  • 如何清除node.js中的超时

    您好 我们正在使用 node js socket io 和 redis 开发应用程序 我们有这个程序 exports processRequest function request result var self this var time
  • ‘state’未定义 no-undef

    我使用教程来学习 React 但我很快就陷入困境 在教程中 他们使用以下代码 import React Component from react class Counter extends Component state count 0 r
  • 如何从 Cloud Functions for Firebase 文件夹读取证书文件

    我正在尝试读取 certs 文件夹下的文件 如下所示 functions certs idp public cert perm 这是我用来读取文件的代码 fs readFileSync path join dirname certs idp
  • Safari 扩展将消息发送到特定选项卡

    有没有办法从全局页面发送消息到特定选项卡 我目前正在做的是 在创建选项卡时 注入的脚本会创建一个唯一的 ID 并将包含该编号的消息发送到全局页面 并且全局页面会保存该编号 如果全局页面需要发送一些数据到一个tab 即 tab 3 然后全局页

随机推荐

  • 使用 jodatime 查找剩余日期和时间

    我想使用 joda 时间进行比较 查找剩余天数和两天之间的时间 我正在使用两个像这样的 DateTime 对象 一个正在开始 另一个正在结束 DateTime endDate new DateTime 2011 12 25 0 0 0 0
  • React Redux mapDispatchToProps 与 this.props.dispatch

    到目前为止 我以这种方式使用容器和组件操作
  • Angular 2 - Typescript 函数与外部 js 库的通信

    Using JavaScript Infovis 工具包作为绘制图形和树的外部库 我需要操作节点的 onClick 方法 以便异步发送 HTTP GET 请求到服务器 并将来自服务器的数据分配给 Angular 服务类的属性和变量 通过使用
  • 将未链接的 Excel 图表粘贴到 Powerpoint

    我目前正在进行一个项目 将 50 多组 Excel 图表传输到 Powerpoint 演示文稿 我正在比较 50 多个项目并制作 50 多个相同的图表 我在 Excel 工作簿中设置的方式是 图表始终是相同的图表 即图表 2 但通过更改唯一
  • 如何获得UCWA和Skype Web SDK的授权?

    我有 Skype for Business 帐户通话 电子邮件受保护 我正在尝试获得授权 我对 lyncdiscover 服务的第一个请求 GET https lyncdiscover shockw4ves onmicrosoft com
  • Sinch SDK - 如何注销用户?

    我正在使用 Sinch SDK 进行即时消息传递 如何注销用户 我有注销用户的按钮 但无法在 Sinch SDK 中实现该功能 他们的文档或示例都没有描述此类功能 sinch客户端没有注销功能 我们认为移动用户是 在线 的 如果您不想接收更
  • 使用 __future__ 还是 future 来编写兼容 python2 和 python3 的代码更好?

    或者在某些特定情况下 其中一种比另一种更好 到目前为止 我所收集到的只是 future 仅适用于 gt 2 6 或 gt 3 3 我当前的代码非常基本 除了使用打印函数调用之外 在 python2 和 3 上运行相同 然而 随着时间的推移
  • Swift 中的宏?

    Swift 目前是否支持宏 或者未来是否计划添加支持 目前我正在分散 Log trace nil function FUNCTION file FILE line LINE 在我的代码的各个地方 在这种情况下 您应该为 宏 参数添加默认值
  • mvtnorm::pmvnorm 的 Rcpp 实现比原始 R 函数慢

    我正在尝试让 pmvnorm 的 Rcpp 版本至少与 R 中的 mvtnorm pmvnorm 一样快 我已经发现https github com zhanxw libMvtnorm并创建了一个带有相关源文件的Rcpp框架包 我添加了以下
  • 子元素点击事件触发父元素点击事件

    假设你有一些这样的代码 div div div div 我不想触发parentDiv当我点击时点击事件childDiv 我怎样才能做到这一点 Updated 另外 这两个事件的执行顺序是怎样的 你需要使用event stopPropagat
  • C strcpy = 未处理的异常:访问冲突写入位置 0x00000000

    我的 strcpy 函数有问题 使用C 这个简单代码 如下 的要点是将字符串从数组复制到指针数组 char string 20 ABCDEFGH 0 char array of pointers 20 now I want to copy
  • Python 中的列表

    python中的List是同质的还是异质的 gt gt gt def a pass gt gt gt lst 1 one 1 one a 1 1 1 True set 1 gt gt gt for each in lst print typ
  • 猫鼬重复键错误与 upsert

    我有重复密钥的问题 找了好久都找不到答案 请帮助我解决这个问题或解释为什么我收到重复的密钥错误 Trace MongoError E11000 duplicate key error collection project monitor i
  • 制作稀疏矩阵时出错

    我面临着一个我不明白的问题 这是建议答案的后续行动here and here 我有两个结构相同的数据集 我创建的一个是代码可以工作的可重现示例 另一个是代码不起作用的真实示例 盯着它几个小时后 我找不到导致错误的原因 下面给出了一个有效的例
  • 如何使用 MockMvc 测试 Spring 控制器方法?

    我正在使用 spring 3 2 0 和 junit 4 这是我需要测试的控制器方法 RequestMapping value Home public ModelAndView returnHome return new ModelAndV
  • 在 Matlab 中通过约束最大化 3x+y

    我需要在 matlab 中最大化方程 3x y 并具有以下约束 2x y 0 我很难弄清楚如何以一种可以将它们与原始方程联系起来的方式加入约束 我是 matlab 新手 很难弄清楚这一点 提前致谢 正如 Franck提到的 你可以一般使用f
  • Oracle 中的字符串聚合:多行合并为单列

    您好 我在 oracle 中有以下字符串聚合函数 CREATE OR REPLACE FUNCTION STRING AGGREGATE i query VARCHAR2 i seperator VARCHAR2 DEFAULT RETUR
  • 在 JavaScript 中将一个项目从一个数组添加到另一个数组之前比较两个数组[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我有两个数组 var addFrom orange banana watermelon lemon peach var addTo pear tangerine grape or
  • C++ 类和相互链接的对象形成一个循环

    我怎样才能实现在C 中形成循环的互锁对象结构 class Foo Bar bar class Bar Foo foo Foo h include
  • 如何从 setTimeout 做出承诺

    这不是一个现实世界的问题 我只是想了解如何创建承诺 我需要了解如何对不返回任何内容的函数做出承诺 例如 setTimeout 假设我有 function async callback setTimeout function callback