代码之家  ›  专栏  ›  技术社区  ›  Tsuna

如何获得[Promise{<pending>}]的结果?[副本]

  •  0
  • Tsuna  · 技术社区  · 6 年前

    这更像是一个概念性的问题。我理解Promise设计模式,但找不到可靠的来源来回答我的问题 promise.all() :

    或者

    有什么最佳实践可供使用吗 答应我。好的() ? 只有当所有promise对象的类型相同或相似时,才应该理想地使用它吗?

    我唯一能想到的是:

    • 答应我。好的() 如果你想兑现诺言 只有 如果 如果有人拒绝,承诺对象中的任何一个都会解决和拒绝。
    0 回复  |  直到 9 年前
        1
  •  66
  •   jfriend00    4 年前

    我不确定是否有人真的给出了最通用的解释何时使用 Promise.all() (不使用时):

    正确的场景是什么答应我。好的()

    答应我。好的() 当您有多个承诺,并且您的代码希望知道这些承诺所代表的所有操作何时成功完成时,它就非常有用。单独的异步操作是什么并不重要。如果它们是异步的,由承诺表示,并且您的代码希望知道它们何时成功完成,那么 就是为了做到这一点。

    例如,假设您需要从三个独立的远程API调用收集信息,并且当您得到所有三个API调用的结果时,您需要使用所有三个结果运行一些进一步的代码。这种情况对我来说是完美的 . 你可以这样做:

    Promise.all([apiRequest(...), apiRequest(...), apiRequest(...)]).then(function(results) {
        // API results in the results array here
        // processing can continue using the results of all three API requests
    }, function(err) {
        // an error occurred, process the error here
    });
    

    可能最常用于类似类型的请求(如上例所示),但没有必要这样做。如果您有一个不同的情况,需要发出远程API请求,读取本地文件并读取本地温度探测器,然后当您有来自所有三个异步操作的数据时,您希望对来自所有三个异步操作的数据进行一些处理,您将再次使用 :

    Promise.all([apiRequest(...), fs.readFileAsync(...), readTemperature(...)]).then(function(results) {
        // all results in the results array here
        // processing can continue using the results of all three async operations
    }, function(err) {
        // an error occurred, process the error here
    });
    

    答应我。好的() .then()

    此外 答应我。好的() 答应我。好的() 答应我。好的() 不会直接帮你的。相反,您可能会使用 Promise.settle() 在那种情况下。你可以看到 an implementation of .settle() here 它允许你访问所有的结果,即使有些结果失败了。当您预期某些操作可能会失败,并且您有一项有用的任务要处理任何成功的操作的结果时,或者您希望检查所有失败的操作的失败原因,以便在此基础上做出决策时,这一点特别有用。

    有什么最佳实践可供使用吗答应我。好的()? 应该是吗

    如上所述,单个异步操作是什么或者它们是否是同一类型并不重要。它只关系到你的代码是否需要协调它们,并知道它们何时都成功。


    使用 答应我。好的()

    1. 当您只有一个异步操作时。只需一次操作,就可以使用 。然后() 答应我。好的() .
    2. 答应我。好的() 不会自己做的。你可能会想要 Promise.allSettled()
    3. 如果异步操作没有全部返回承诺, 答应我。好的() 无法跟踪未通过承诺管理的异步操作。
        2
  •  5
  •   joews    9 年前

    Promise.all 等待几个承诺同时解决。当所有输入承诺都已解决时,它返回一个已解决的承诺:

    // p1, p2, p3 are Promises
    Promise.all([p1, p2, p3])
      .then(([p1Result, p2Result, p3Result]) => {
        // This function is called when p1, p2 and p3 have all resolved.
        // The arguments are the resolved values.
      })
    

    如果 如果拒绝输入承诺,则 也被拒绝了。

    一个常见的场景是等待几个API请求完成,以便您可以合并它们的结果:

     const contentPromise = requestUser();
     const commentsPromise = requestComments();
    
     const combinedContent = Promise.all([contentPromise, commentsPromise])
       .then(([content, comments]) => {
         // content and comments have both finished loading.
       })
    

    你可以用 答应我。好的 具有 Promise

        3
  •  3
  •   sdgluck    9 年前

    很难回答这些问题,因为当使用语言特性的可用api时,这些问题往往会自己回答。基本上,以任何适合您的用例的方式使用承诺都是可以的,只要您避免使用它们 anti-patterns .

    正确的场景是什么答应我。好的()

    有什么最佳实践可供使用吗答应我。好的()? 只有当所有promise对象的类型相同或相似时,才应该理想地使用它吗?

        4
  •  3
  •   miquelarranz    9 年前

    promise.all() 当我必须对我的API做一些请求时,我不想在应用程序加载所有请求的数据之前显示一些内容,所以我会延迟执行流,直到我得到所有需要的数据。

    例子:

    我想做什么 在我的应用程序中显示一个包含用户电子邮件和每个用户的产品名称的表之前,我想加载我的应用程序的用户及其产品(假设你必须执行多个请求)。

    我接下来做什么 我将请求发送到我的API,创建承诺并使用 答应我。好的()

    当所有的数据都被加载后我该怎么办 一旦数据到达我的应用程序,我就可以执行 promises.all()

    我希望它能帮助您了解在哪种情况下使用 承诺。全部()

        5
  •  0
  •   Callum Linington    9 年前

    我倾向于用promise all来做这样的事情:

    myService.getUsers()
       .then(users => {
           this.users = users;
    
           var profileRequests = users.map(user => {
               return myService.getProfile(user.Id); // returns a promise
           });
    
           return Promise.all(profileRequests);
       })
       .then(userProfilesRequest => {
           // do something here with all the user profiles, like assign them back to the users.
    
           this.users.forEach((user, index) => {
               user.profile = userProfilesRequest[index];
           });
       });
    

    x 要解决的承诺数量。

    Promise.all() 基本上将我所有的承诺聚合成一个,我可以通过下一个来实现 then . 我可以一直这样做,只要一个喜欢,说为每个配置文件,我想得到相关的设置等,每次我创造更多的承诺,我可以把他们都聚集成一个。

        6
  •  0
  •   Nancy thakkar    9 年前

    2.只需使用答应我。好的(文件).catch(err=>{})

    3.使用。反思之前的承诺。如果你想等待所有的一切 拒绝或履行的承诺

    1. 语法-答应我。好的(可替代的);
        7
  •  0
  •   Venky    9 年前

    Promise.all

    https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

    var isCallFailed = false;
    function myEndpoint1() {
      return isCallFailed ? Promise.reject("Bohoo!") :Promise.resolve({"a":"a"});
    }
    function myEndpoint2() {
      return Promise.resolve({"b":"b"});
    }
    
    Promise.all([myEndpoint1(), myEndpoint2()])
    .then(values => {
      var data1 = values[0];
      var data2 = values[1];
      alert("SUCCESS... data1: " + JSON.stringify(data1) + "; data2: " +  JSON.stringify(data2));
    })
    .catch(error => {
      alert("ERROR... " + error);
    });
    

    你可以通过 isCallFailed = true .

        8
  •  0
  •   GalAbra    4 年前

    Promise.all 应该明确指出的是,它使您的异步代码 快得多

    这使得它非常适合于任何包含独立调用的代码(我们希望在代码的其余部分继续之前返回/完成这些调用),尤其是当我们进行前端调用并希望用户体验尽可能平滑时。

    async function waitSecond() {
      return new Promise((res, rej) => {
        setTimeout(res, 1000);
      });
    }
    
    function runSeries() {
      console.time('series');
      waitSecond().then(() => {
        waitSecond().then(() => {
          waitSecond().then(() => {
            console.timeEnd('series');
          });
        });
      });
    }
    
    function runParallel() {
      console.time('parallel');
      Promise.all([
        waitSecond(),
        waitSecond(),
        waitSecond(),
      ]).then(() => {
        console.timeEnd('parallel');
      });
    }
    
    runSeries();
    runParallel();
        9
  •  -2
  •   Vanya Avchyan    9 年前

    承诺-是一个特殊的对象,包含你的状态。最初,挂起(等待),然后-其中之一:已完成(已成功)或已拒绝(已完成但有错误)。

    关于挂起的承诺,回调可以有两种类型:

    • “成功。”
    • 拒绝-在“错误中作出”的承诺时触发

    var promise = new Promise(function(resolve, reject) {
      // This function will be called automatically
    
      // It is possible to make any asynchronous operations,
      // And when they will end - you need to call one of:
      // resolve(result) on success
      // reject(error) on error
    })
    

    悬挂手柄的通用方法:

    promise.then(onFulfilled, onRejected)
    
    • onimplemented—将使用 决心。

    • onRejected—当错误被拒绝时将调用的函数。

    在它的帮助下,您可以一次分配两个处理程序,并且只能分配一个:

    // onFulfilled It works on success
    promise.then(onFulfilled)
    // onRejected It works on error
    promise.then(null, onRejected)
    

    同步抛出-与拒绝相同

    'use strict';
    
    let p = new Promise((resolve, reject) => {
      // то же что reject(new Error("o_O"))
      throw new Error("o_O");
    });
    
    p.catch(alert); // Error: o_O
    

    承诺

    在承诺之后,功能性的使用往往变得更加方便。

    httpGet函数(url)将返回PROMIS,在成功加载带有url的数据后,PROMIS将与这些数据一起进入completed,如果出现错误,则返回错误信息:

    function httpGet(url) {
    
        return new Promise(function(resolve, reject) {
    
            var xhr = new XMLHttpRequest();
            xhr.open('GET', url, true);
    
            xhr.onload = function() {
                if (this.status == 200) {
                    resolve(this.response);
                } else {
                    var error = new Error(this.statusText);
                    error.code = this.status;
                    reject(error);
                }
            };
    
            xhr.onerror = function() {
                reject(new Error("Network Error"));
            };
    
            xhr.send();
        });
    
    }
    

    如您所见,在函数内,当onload/onerror分别被调用时,XMLHttpRequest对象像往常一样被创建和发送,即resolve(状态为200)或reject。

    使用:

    httpGet("/article/promise/user.json")
        .then(
            response => alert(`Fulfilled: ${response}`),
            error => alert(`Rejected: ${error}`)
        );
    

    如果我们想同时实现多个异步进程并处理它们的结果呢?

    Promise类具有以下静态方法。

    答应我。好的(可编辑)

    例如:

    Promise.all([
        httpGet('/article/promise/user.json'),
        httpGet('/article/promise/guest.json')
    ]).then(results => {
        alert(results);
    });
    

    假设我们有一个URL数组。

    let urls = [
      '/article/promise/user.json',
      '/article/promise/guest.json'
    ];
    

    要并行下载它们,您需要:

    1. 将PROMIS数组包装在答应我。好的.

    我们得到:

    '使用严格';

    let urls = [
      '/article/promise/user.json',
      '/article/promise/guest.json'
    ];
    
    Promise.all( urls.map(httpGet) )
      .then(results => {
        alert(results);
    });
    

    请注意,如果任何一个承诺以错误结束,结果将是

    答应我。好的这个错误。

    例如:

    Promise.all([
        httpGet('/article/promise/user.json'),
        httpGet('/article/promise/guest.json'),
        httpGet('/article/promise/no-such-page.json') // (нет такой страницы)
    ]).then(
        result => alert("не сработает"),
        error => alert("Ошибка: " + error.message) // Ошибка: Not Found
    )
    

    总计:

    • 结果(如果有),以及回调。
    • 创建新的承诺((resolve,reject)=>函数时 参数自动启动,该参数应在上调用resolve(result) 成功,拒绝(错误)-错误。
    • 是传递给处理者的。
    • 通过调用.then/catch指定处理程序。
    • 使用更改将结果从一个处理器传输到另一个处理器。

    https://www.promisejs.org/patterns/