这不是现实问题,我只是想了解如何创建承诺。
我需要了解如何对不返回任何内容的函数(例如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年,Promises内置在JavaScript中,并由ES2015规范添加(polyfill可用于IE8-IE11等过时的环境)。他们使用的语法使用传递给Promise
构造函数(Promise
executor)的回调,该回调函数接收用于解析/拒绝promise的函数作为参数。
首先,由于async
现在在JavaScript中具有含义(即使在某些情况下只是一个关键字),我将使用它later
作为函数的名称以避免混淆。
使用本机的Promise(或忠实的polyfill)看起来像这样:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
需要注意的是,它假定的一个版本,setTimeout
这是符合该定义的浏览器,其中setTimeout
不传递任何参数的回调,除非你给他们的时间间隔后(这可能不是在非浏览器环境中真实的,并没有曾经是在Firefox上为true,但现在是;在Chrome上甚至在IE8上都为true)。
如果您希望函数有选择地传递分辨率值,请在任何模糊的现代浏览器上允许您setTimeout
在延迟后提供额外的参数,然后在调用时将其传递给回调,您可以执行此操作(当前Firefox和Chrome;IE11 + ,大概是Edge; 不是 IE8或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));
}
甚至
const later = (delay, value) =>
new Promise(resolve => setTimeout(resolve, delay, value));
如果您想取消超时,则不能只从中返回承诺later
,因为不能取消承诺。
但是,我们可以轻松地用cancel
承诺的方法和访问器返回对象,并在取消时拒绝承诺:
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);
通常,您将拥有一个Promise库(一个是您自己编写的,或者是其中几个库中的一个)。该库通常会有一个您可以创建并稍后“解析”的对象,而该对象将有一个您可以从中获得的“承诺”。
然后later
往往看起来像这样:
function later() {
var p = new PromiseThingy();
setTimeout(function() {
p.resolve();
}, 2000);
return p.promise(); // Note we're not returning `p` directly
}
在对问题的评论中,我问:
您是否正在尝试创建自己的Promise库?
你说
我不是,但我现在想这就是我想要了解的内容。那图书馆怎么做
<!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>
问题内容: 我有一个简单的JavaScript可以加载声音: 我有一项执行以下功能的服务: 我想要的是对声音的简单承诺,所以当我调用它时,我会遇到类似以下情况: 那有可能吗? 问题答案: 您可以实施设置: 现在您可以致电: 由于音频元素的缓冲行为,因此没有意义。指示预加载将告诉浏览器您要播放音频文件。在我看来,这对于客户端和系统也更好。
问题内容: 在这里,我试图绕过Promise.Here在第一个请求时获取一组链接。在下一个请求时,我获取第一个链接的内容。但是我想在返回下一个Promise对象之前进行延迟。所以我使用setTimeout就可以了,但是它给了我下面的JSON错误( ) SyntaxError:JSON.parse:JSON数据的第1行第1列出现意外字符 我想知道为什么会失败? 问题答案: 为了保持承诺链的进行,您不
问题内容: 标题输出很好,但是内容却没有。它里面有一些html,我得到了以下错误:像这样描述:http : //docs.angularjs.org/error/ $ sce:unsafe,这很好,但是那我怎么能在那里输出内容将在其中一些HTML,所以我必须将其设置为或smthn。正确的方法是什么? 编辑: AngularJS版本:1.2 问题答案: 因此解决方法是: 从http://code.a
问题内容: 我已经在这个项目上工作了大约一个星期,而且我已经搜索了2天,但没有任何明确的在线解释。对于学校作业,我们需要使用以下程序设置构建服务器: Maven,作为我们的构建工具。 Mercurial作为我们的版本控制系统。 Java(JRE),javac和javadoc。 JUnit用于单元测试。 Jenkins(带有JDepend插件)。 我们需要创建3个工作,其中一个工作是: 每次修改(本
本文向大家介绍简单通过settimeout看javascript的运行机制,包括了简单通过settimeout看javascript的运行机制的使用技巧和注意事项,需要的朋友参考一下 前言 我们知道JS是一个单线程的语言,而且其运行机制比较特殊。 下面我们通过settimeout的几个示例来展现javascript的运行机制的特殊点 示例1 示例2 javascript会先把需要运行的内容放到任务
问题内容: 在我的页面上,我正在通过JavaScript更改某些CSS样式。当我尝试提取一个已继承的值时-它变成空白。考虑以下: 和html: 如果我查看元素’ document.getElementById(objname).style.display ‘其空白?如何通过javascript读取显示值? 问题答案: 您将要使用getComputedStyle。 该属性是访问和设置内联样式的方式(