Javascript 如何从`setTimeout`回调中获取返回值?

Javascript 如何从`setTimeout`回调中获取返回值?,javascript,ecmascript-6,Javascript,Ecmascript 6,考虑一下这个代码 const obj = { generate(num) { return Math.random()*num; }, add(a,b) { return this.generate(a) + this.generate(b) } }; function delay(func, ms) { function wrapper() { setTimeout(() => func.apply(this, arguments), ms)

考虑一下这个代码

const obj = {
  generate(num) {
    return Math.random()*num;
  },
  add(a,b) {
    return this.generate(a) + this.generate(b)
  }
};

function delay(func, ms) {
  function wrapper() {
    setTimeout(() => func.apply(this, arguments), ms)  // How can I get the return value from the original function?
  }

  return wrapper;
}

// create wrappers
obj.f1000 = delay(obj.add, 1000);
obj.f1500 = delay(obj.add, 1500);

obj.f1000(1,3);
obj.f1500(2,5);
我制作了一个包装器来延迟
add()

有没有一种方法可以从setTimeout内部的回调中检索值,即
this.generate(a)+this.generate(b)
from
add()

由于setTimeout将异步执行回调,因此您需要使用承诺(ES6)或异步/等待(ES7)

你可以在ES5中使用它

以身作则
const obj={
生成(num){
返回Math.random()*num;
},
加(a、b){
返回this.generate(a)+this.generate(b);
}
};
//创造承诺
函数timedPromise(函数、参数、毫秒){
返回新承诺(解决=>{
设置超时(()=>{
//扩展运算符
解析(函数应用(null,参数));
},ms);
});
}
//创建创建承诺的函数
功能延迟(func,ms){
函数包装器(){
返回timedPromise(函数、参数、毫秒);
}
返回包装器;
}
//obj.add使用this.generate,但“this”未绑定到obj
obj.f1000=延迟(obj.add.bind(obj),1000);
obj.f1500=延迟(obj.add.bind(obj),1500);
console.info('正在计算…')
const result1=obj.f1000(1,3);
常数结果2=对象f1500(2,5);
结果1.然后(结果=>{
控制台信息(“f1000”,结果);
})
结果2.然后(结果=>{
控制台信息(“f1500”,结果);

})
只需在包装中更改这一行:

setTimeout(() => func.apply(this, arguments), ms) 
返回a(ES6)

您可以通过
访问延迟结果。然后

更新根据OP的请求,编辑答案以使用
async/await
代替
then
。由于
await
需要在声明为
async
的函数中调用,因此我们需要将js代码封装在新函数中(
main()
如下):

const obj={
生成(num){
返回Math.random()*num;
},
加(a、b){
返回this.generate(a)+this.generate(b)
},
};
功能延迟(func,ms){
函数包装器(){
//换行
返回新的承诺(resolve=>setTimeout(()=>resolve(func.apply(this,arguments)),ms));//如何从原始函数获取返回值?
}
返回包装器;
}
//Wait只能在“异步”函数中工作
异步函数main(){
obj.f1000=延迟(obj.add,1000);
控制台。时间(“完成”);
//在此添加等待
设x=等待对象f1000(1,3);
控制台日志(x);
控制台。时间结束(“已完成”);
}

main()注意:不能使用polyfill异步/等待语法。您只能传输它(即使用Babel)。您可以使用
async/await
重写此示例吗?您可以使用async/await重写此示例吗?可以,但要使用
await
而不是
。然后
您需要先将该代码包装在声明为
async
的函数中。更新了上面的示例代码。
return new Promise(resolve => setTimeout(() => resolve(func.apply(this, arguments)), ms));