Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/474.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何从setTimeout做出承诺_Javascript_Settimeout_Promise - Fatal编程技术网

Javascript 如何从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准备好回调(

这不是现实世界的问题,我只是想了解承诺是如何产生的

我需要了解如何保证函数不返回任何内容,比如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);
    });
}
请注意,假设符合where
setTimeout
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
is
const
)。将其作为只读数据属性写入将更加详细。:-)
//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);
  });