javascript 函数数组的Promise/then

noj0wjuj  于 2023-04-10  发布在  Java
关注(0)|答案(3)|浏览(134)

我有一个函数数组,例如:

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函数被解析时被调用。

ldioqlga

ldioqlga1#

根据mdn web文档,fetch()将返回Promise,因此它将首先打印Hello, world!而不是window.x的值,因为window.xPromise。因此,在使用async函数打印之前,必须首先解析fetch响应,如下所示:

let funcs = []
funcs.push(() => {
  window.x = new Promise((resolve, reject) => {
    fetch('https://dummyjson.com/carts/1')
    .then(result => result.json())
    .then(response => resolve(response))
    .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();
  }
})()
zpgglvta

zpgglvta2#

你的一些函数涉及异步操作,当你认为这样的函数是“resolved”时,你必须清楚。更确切地说,如果你想等待某个结果,你的函数必须为那个结果返回一个promise。例如,fetch为一个response对象返回一个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);
yiytaume

yiytaume3#

您可以在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);

相关问题