我有一系列函数,例如:
let funcs = []
funcs.push(() => {window.x = fetch()})
funcs.push(() => {console.log(window.x)})
funcs.push(() => {console.log("Hello, world!")})
我希望函数一个接一个地被调用,如:
for (let func of funcs) {
func();
}
然而,我想把这些函数连接起来,就好像它们是Promises一样,这样N+1函数只有在解析N函数时才会被调用。
您的一些函数涉及异步操作,当您考虑这样的函数时必须明确"解决";。更确切地说,如果您想等待某个结果,那么您的函数必须返回该结果的promise。例如,fetch
返回响应对象的promise:
funcs.push(() => {return window.x = fetch(...)});
但您也可以等待响应体完全消耗掉:
funcs.push(() => {return window.x = fetch(...).then(r => r.text())});
像第二个和第三个这样的同步函数不需要返回任何内容。
有了它,你可以使用以下代码来一个接一个地执行它们:
let promise = Promise.resolve();
for (const func of funcs) promise = promise.then(func);
根据mdn web文档,fetch()
将返回Promise
,因此它将首先打印Hello, world!
,而不是window.x
的值,因为window.x
是Promise
。因此,在使用async
函数打印之前,您必须首先解析获取响应,如下所示:
let funcs = []
funcs.push(() => {
window.x = new Promise((resolve, reject) => {
fetch('https://dummyjson.com/carts/1')
.then(result => resolve(result.json()))
.catch(error => reject(error));
});
});
funcs.push(async() => { console.log(await window.x) });
funcs.push(() => { console.log("Hello, world!") });
(async() => {
for (let func of funcs) {
await func();
}
})()
您可以混合"正常的";函数,函数在funcs
数组中返回promise,但您必须确保promise(如果有…)实际上是生成函数生成的returned
,而不仅仅是生成的。我去掉了第一个函数周围的大括号({
,}
),并确保它返回一个";明智的";值(通过向其提供另外的.then(r=>r.json()).then(d=>window.x=d.username)
)。
一旦设置了funcs
数组,您就可以使用await
关键字在async
函数中连续运行单个函数,如下所示:
const url="https://jsonplaceholder.typicode.com/users/"; // public API for testing ...
let funcs = [
() => fetch(url+3).then(r=>r.json()).then(d=>window.x=d.username), // returns a promise
() => {console.log(window.x+` is the same as global x: ${x}`)}, // returns nothing
() => {console.log("Hello, world!")} ]; // returns nothing
async function doit(fns){ for (let fn of fns) await fn() }
doit(funcs);
使用像window.x
这样的全局变量通常不是一个好主意。我把它放在这里只是为了表明理论上你的方法是可行的。然而,获得promise结果的更好方法是通过最后一个链接的then()
方法返回所需的值,并通过用await
等待它的表达式来获取它。但是,当然,您的第二个函数也需要更改,以便而不是使用全局x
,而是使用给定的参数val
:
const url="https://jsonplaceholder.typicode.com/users/"; // public API for testing ...
let funcs = [
() => fetch(url+3).then(r=>r.json()).then(d=>d.username), // returns a promise
(val) => {console.log(`This is val: ${val}`)}, // returns nothing
() => {console.log("Hello, world!")} ]; // returns nothing
async function doit(fns){
let v;
for (let fn of fns) v=await fn(v); // v gets re-evaluated each time!
}
doit(funcs);