Javascript 如何从setTimeout做出承诺
这不是现实世界的问题,我只是想了解承诺是如何产生的 我需要了解如何保证函数不返回任何内容,比如setTimeout 假设我有:Javascript 如何从setTimeout做出承诺,javascript,settimeout,promise,Javascript,Settimeout,Promise,这不是现实世界的问题,我只是想了解承诺是如何产生的 我需要了解如何保证函数不返回任何内容,比如setTimeout 假设我有: function async(callback){ setTimeout(function(){ callback(); }, 5000); } async(function(){ console.log('async called back'); }); 如何创建一个承诺,即async可以在setTimeout准备好回调(
function async(callback){
setTimeout(function(){
callback();
}, 5000);
}
async(function(){
console.log('async called back');
});
如何创建一个承诺,即async
可以在setTimeout
准备好回调()后返回
我想包装它会带我去某个地方:
function setTimeoutReturnPromise(){
function promise(){}
promise.prototype.then = function() {
console.log('timed out');
};
setTimeout(function(){
return ???
},2000);
return promise;
}
但我无法超越这一点。Update(2017)
2017年,承诺被内置到JavaScript中,它们由ES2015规范添加(polyfills可用于过时的环境,如IE8-IE11)。它们所使用的语法使用了一个回调函数,您可以将它传递到Promise
构造函数(Promise
执行器)中,该构造函数接收用于解析/拒绝作为参数的Promise的函数
首先,因为(即使在某些上下文中它只是一个关键字),我稍后将使用作为函数名,以避免混淆
基本延迟
使用本机承诺(或忠实的polyfill),它将如下所示:
function later(delay) {
return new Promise(function(resolve) {
setTimeout(resolve, delay);
});
}
请注意,假设符合wheresetTimeout
的setTimeout
版本不会向回调传递任何参数,除非您在间隔后给出参数(这在非浏览器环境中可能不正确,在Firefox上也不正确,但现在是这样;在Chrome上甚至在IE8上也是如此)
带值基本延迟
如果您想让函数有选择地在任何模糊的现代浏览器上传递解析值,该浏览器允许您在延迟后为setTimeout
提供额外参数,然后在调用时将这些参数传递给回调函数,您可以这样做(当前的Firefox和Chrome;IE11+,大概是Edge;不是IE8或IE9,不知道IE10):
如果您使用的是ES2015+箭头函数,则更为简洁:
function later(delay, value) {
return new Promise(resolve => setTimeout(resolve, delay, value));
}
甚至
const later = (delay, value) =>
new Promise(resolve => setTimeout(resolve, delay, value));
带值可取消延迟
如果您想取消超时,就不能稍后从返回承诺,因为承诺不能取消
但是,我们可以很容易地使用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;
}
}
};
};
实例:
constlater=(延迟,值)=>{
设定时器=0;
让reject=null;
const promise=新承诺((解决,拒绝)=>{
拒绝=_拒绝;
定时器=设置超时(解析、延迟、值);
});
返回{
get promise(){return promise;},
取消{
中频(定时器){
清除超时(计时器);
定时器=0;
拒绝();
拒绝=空;
}
}
};
};
常数l1=之后的值(100,“l1”);
l1.承诺
.then(msg=>{console.log(msg);})
.catch(()=>{console.log(“l1已取消”);});
常数l2=后(200,“l2”);
承诺
.then(msg=>{console.log(msg);})
.catch(()=>{console.log(“l2已取消”);});
设置超时(()=>{
l2.取消();
},150);
这不是对原始问题的回答。但是,由于原始问题不是现实世界中的问题,它不应该是问题。我试图向朋友解释JavaScript中的承诺是什么,以及承诺和回调之间的区别
以下代码作为解释:
//very basic callback example using setTimeout
//function a is asynchronous function
//function b used as a callback
function a (callback){
setTimeout (function(){
console.log ('using callback:');
let mockResponseData = '{"data": "something for callback"}';
if (callback){
callback (mockResponseData);
}
}, 2000);
}
function b (dataJson) {
let dataObject = JSON.parse (dataJson);
console.log (dataObject.data);
}
a (b);
//rewriting above code using Promise
//function c is asynchronous function
function c () {
return new Promise(function (resolve, reject) {
setTimeout (function(){
console.log ('using promise:');
let mockResponseData = '{"data": "something for promise"}';
resolve(mockResponseData);
}, 2000);
});
}
c().then (b);
我们可以像下面这样传递自定义“cb fxn”实现:
//Promisify setTimeout
常数暂停=(毫秒,cb,…参数)=>
新承诺((解决、拒绝)=>{
setTimeout(异步()=>{
试一试{
解析(等待cb?(…参数))
}捕获(错误){
拒绝(错误)
}
},ms)
})
测试:
//测试1
暂停(1000)。然后(()=>console.log('called'))
//测试2
暂停(1000,(a,b,c)=>a,b,c],1,2,3)。然后(值=>console.log(值))
//测试3
暂停(1000,()=>{
抛出错误('foo')
}).catch(错误=>console.error(错误))
您是否正在尝试创建自己的promise库?@T.J.Crowder我没有,但我想现在这正是我试图理解的。库将如何做到这一点@滞后:是有道理的,我在答案中添加了一个基本promise实现示例。我认为这是一个非常现实的问题,我必须为一个大型项目解决这个问题我的公司正在建设。可能有更好的方法可以做到这一点,但为了我们的蓝牙协议栈,我基本上需要延迟承诺的解决方案。我将在下面的帖子中展示我所做的。请注意,在2017年,“async”对于一个函数来说是一个有点混乱的名称,因为您可能有async function async(){…}
related:)你的答案不合适cancelTimeout@AlexanderDanilov:承诺不可撤销。您当然可以编写一个函数,该函数返回一个带有cancel方法的对象,并分别返回承诺的访问器,然后在调用cancel方法时拒绝承诺…@AlexanderDanilov:我继续添加了一个。@Leon-前者使承诺为只读,因此,您不能在返回的对象上分配给promise
。我不清楚为什么我把它写为一个访问器,而不是一个实际的只读数据属性。可能是懒惰——访问器有一个很好的紧凑语法,我无法想象任何半体面的JavaScript引擎在正常情况下都不会优化函数调用(因为promise
isconst
)。将其作为只读数据属性写入将更加详细。:-)
//very basic callback example using setTimeout
//function a is asynchronous function
//function b used as a callback
function a (callback){
setTimeout (function(){
console.log ('using callback:');
let mockResponseData = '{"data": "something for callback"}';
if (callback){
callback (mockResponseData);
}
}, 2000);
}
function b (dataJson) {
let dataObject = JSON.parse (dataJson);
console.log (dataObject.data);
}
a (b);
//rewriting above code using Promise
//function c is asynchronous function
function c () {
return new Promise(function (resolve, reject) {
setTimeout (function(){
console.log ('using promise:');
let mockResponseData = '{"data": "something for promise"}';
resolve(mockResponseData);
}, 2000);
});
}
c().then (b);
const setTimeoutAsync = (cb, delay) =>
new Promise((resolve) => {
setTimeout(() => {
resolve(cb());
}, delay);
});