Javascript 目标承诺,不可能获得价值
我有一些异步函数:Javascript 目标承诺,不可能获得价值,javascript,object,asynchronous,promise,Javascript,Object,Asynchronous,Promise,我有一些异步函数: async global(){ return 'Test success' } 我把这叫做我的钩子,它必须实现: const Controller = use('App/Controllers/Http/Controller') View.global('ShowGlobal', async () => { const call = new Controller() const info = await call.global()
async global(){
return 'Test success'
}
我把这叫做我的钩子,它必须实现:
const Controller = use('App/Controllers/Http/Controller')
View.global('ShowGlobal', async () => {
const call = new Controller()
const info = await call.global()
console.log(info)
return info
})
同时,我得到了正确的console.log,结果为“testsuccess”,但return不断地给我[objectpromise]
我做错了什么?(这是我找到的答案)
您在JavaScript中编写的代码在一个线程上运行,这意味着如果您的代码实际上可以等待一些东西,那么它将阻止任何其他代码执行。JavaScript的事件循环在本视频中得到了很好的解释,如果您愿意阅读本页的话
浏览器中阻止代码的一个很好的例子是警报(“在单击“确定”之前无法执行任何操作”);。警报会阻止一切,用户甚至无法滚动或单击页面中的任何内容,您的代码也会阻止执行
Promise.resolve(22)
.then(x=>alert("blocking")||"Hello World")
.then(
x=>console.log(
"does not resolve untill you click ok on the alert:",
x
)
);
在控制台中运行它,你就会明白我所说的阻塞是什么意思了
当你想做一些需要时间的事情时,这就产生了一个问题。在其他框架中,您可能会使用线程或进程,但JavaScript中没有这样的东西(从技术上讲,web worker和fork-In-node是这样的,但这是另一回事,通常比使用异步api复杂得多)
因此,当您想要发出http请求时,可以使用fetch,但fetch需要一些时间才能完成,并且您的函数不应该阻塞(必须尽快返回某些内容)。这就是fetch返回承诺的原因
请注意,fetch是由browser/node实现的,并在另一个线程中运行,只有您编写的代码在一个线程中运行,因此启动大量承诺,即仅运行您编写的代码不会加快任何速度,但并行调用本机异步api会加快速度
在承诺之前,异步代码使用回调或返回可观察对象(如XmlHttpRequest),但让我们讨论承诺,因为您可以将更传统的代码转换为承诺
承诺是一个对象,它有一个then函数(和一堆对then来说是糖的东西,但做的是相同的),这个函数有两个参数
Resolve handler:承诺解析时(无错误且已完成)将由承诺调用的函数。函数将被传递一个带有resolve值的参数(对于http请求,这通常是响应)。
拒绝处理程序:当承诺拒绝(有错误)时,承诺将调用的函数。此函数将被传递一个参数,这通常是错误或拒绝的原因(可以是字符串、数字或任何内容)。
将回调转换为承诺
传统api(尤其是nodejs api)使用回调:
traditionalApi(
arg
,function callback(err,value){
err ? handleFail(err) : processValue(value);
}
);
这使得程序员很难捕捉错误或以线性方式(从上到下)处理返回值。通过错误处理(无法读取)来并行或限制并行地尝试和执行任务变得更加不可能
您可以将传统api转换为具有新承诺的承诺
const apiAsPromise = arg =>
new Promise(
(resolve,reject)=>
traditionalApi(
arg,
(err,val) => (err) ? reject(err) : resolve(val)
)
)
async await
这就是所谓的承诺语法糖。它使承诺消费函数看起来更传统,更易于阅读。也就是说,如果您喜欢编写传统代码,我认为编写小函数更容易阅读。例如,你能猜出这是做什么的吗
const handleSearch = search =>
compose([
showLoading,
makeSearchRequest,
processRespose,
hideLoading
])(search)
.then(
undefined,//don't care about the resolve
compose([
showError,
hideLoading
])
);
歪道;别再唠叨了。重要的一点是要理解async await实际上不会启动另一个线程,异步函数总是返回一个承诺,而await实际上不会阻塞或等待。这是someFn()的语法。然后(结果=>…,错误=>…)看起来像:
async someMethod = () =>
//syntax sugar for:
//return someFn().then(result=>...,error=>...)
try{
const result = await someFn();
...
}catch(error){
...
}
}
示例始终显示try catch,但您不需要这样做,例如:
var alwaysReject = async () => { throw "Always returns rejected promise"; };
alwaysReject()
.then(
x=>console.log("never happens, doesn't resolve")
,err=>console.warn("got rejected:",err)
);
抛出或等待返回被拒绝的承诺的任何错误都将导致异步函数返回被拒绝的承诺(除非您尝试捕获它)。很多时候,让它失败并让调用者处理错误是可取的
如果希望承诺成功,并为被拒绝的承诺指定一个特殊值,以便稍后处理,则可能需要捕获错误,但承诺在技术上不会拒绝,因此将始终解决
例如Promise.all,它接受一个承诺数组并返回一个新的承诺,该承诺解析为一个解析值数组,或者在其中任何一个拒绝时拒绝。您可能只想获得所有承诺的结果,并过滤掉被拒绝的承诺:
const Fail = function(details){this.details=details;},
isFail = item => (item && item.constructor)===Fail;
Promise.all(
urls.map(//map array of urls to array of promises that don't reject
url =>
fetch(url)
.then(
undefined,//do not handle resolve yet
//when you handle the reject this ".then" will return
// a promise that RESOLVES to the value returned below (new Fail([url,err]))
err=>new Fail([url,err])
)
)
)
.then(
responses => {
console.log("failed requests:");
console.log(
responses.filter(//only Fail type
isFail
)
);
console.log("resolved requests:");
console.log(
responses.filter(//anything not Fail type
response=>!isFail(response)
)
);
}
);
您需要
等待ShowGlobal()
当您调用它时,您的选项是。。。。使用承诺,或弃船。需要时间旅行来避免需要承诺(也就是说,或者做任何要求值async
的事情)。所有async
函数都会返回一个承诺。async
函数的调用方必须使用.then()
或wait
从该承诺中获取值。从async
函数返回的值将成为该函数返回的承诺的解析值。这就是所有的async
函数的工作原理-没有其他方法可以解决。从中复制和粘贴是不好的,如果整个答案都适用,那么将问题标记为重复可能是更好的选择。如果部分答案适用,至少使用引号块(这样人们就知道是别人写的)并链接原始答案以给予适当的信任。