Sök…


Syntax

  • ny Löfte (/ * exekutivfunktion: * / funktion (lösa, avvisa) {})
  • lover.then (onFulfilled [, onRejected])
  • promise.catch (onRejected)
  • Promise.resolve (upplösning)
  • Promise.reject (orsak)
  • Promise.all (iterable)
  • Promise.race (iterable)

Anmärkningar

Löften är en del av ECMAScript 2015-specifikationen och webbläsarsupport är begränsat, med 88% av webbläsarna världen över som stöder det från juli 2017. Följande tabell ger en översikt över de tidigaste webbläsarversionerna som ger stöd för löften.

Krom Kant Firefox Internet Explorer Opera Opera Mini Safari iOS Safari
32 12 27 x 19 x 7,1 8

I miljöer som inte stöder dem kan Promise polyfyllas. Tredjepartsbibliotek kan också tillhandahålla utökade funktioner, till exempel automatiserad "promisification" av återuppringningsfunktioner eller ytterligare metoder som progress - även känd som notify .

Promises / A + standardwebbplatsen innehåller en lista med 1.0 och 1.1-kompatibla implementationer . Löfte återuppringningar baserade på A + -standarden utförs alltid asynkront som mikrotaskar i händelsslingan .

Löfte kedja

Den then metoden för ett löfte ger ett nytt löfte.

const promise = new Promise(resolve => setTimeout(resolve, 5000));

promise
    // 5 seconds later
    .then(() => 2)
    // returning a value from a then callback will cause
    // the new promise to resolve with this value
    .then(value => { /* value === 2 */ });

Returnera en Promise från en then återuppringning kommer att lägga till löftet kedjan.

function wait(millis) {
    return new Promise(resolve => setTimeout(resolve, millis));
}

const p = wait(5000).then(() => wait(4000)).then(() => wait(1000));
p.then(() => { /* 10 seconds have passed */ });

En catch tillåter ett avvisat löfte att återhämta sig, liknande hur catch i ett try / catch fungerar. Alla kedjade then efter en catch kommer att utföra sin upplösningshanterare med hjälp av det värde som löses från catch .

const p = new Promise(resolve => {throw 'oh no'});
p.catch(() => 'oh yes').then(console.log.bind(console));  // outputs "oh yes"

Om det inte finns några catch eller reject hanterare i mitten av kedjan, kommer en catch i slutet att fånga avslag i kedjan:

p.catch(() => Promise.reject('oh yes'))
  .then(console.log.bind(console))      // won't be called
  .catch(console.error.bind(console));  // outputs "oh yes"

Vid vissa tillfällen kanske du vill "grenas" utförandet av funktionerna. Du kan göra det genom att returnera olika löften från en funktion beroende på villkor. Senare i koden kan du slå samman alla dessa grenar till en för att kalla andra funktioner på dem och / eller för att hantera alla fel på ett ställe.

promise
    .then(result => {          
        if (result.condition) {
            return handlerFn1() 
                .then(handlerFn2);
        } else if (result.condition2) {
            return handlerFn3()
                .then(handlerFn4);
        } else {
            throw new Error("Invalid result");
        }
    })
    .then(handlerFn5)
    .catch(err => {
        console.error(err);
    });

Således ser exekveringsordning för funktionerna ut:

promise --> handlerFn1 -> handlerFn2 --> handlerFn5 ~~> .catch()
         |                            ^
         V                            |
         -> handlerFn3 -> handlerFn4 -^            

Den enskilda catch får felet på vilken gren den än kan förekomma.

Introduktion

Ett Promise representerar en operation som har producerat eller så småningom ger ett värde. Löften ger ett robust sätt att ta bort det (eventuellt pågående) resultatet av asynkront arbete, vilket mildrar problemet med djupt kapslade återuppringningar (känd som " callback helvete ").

Tillstånd och kontrollflöde

Ett löfte kan vara i en av tre stater:

  • avvaktande - Den underliggande operationen har ännu inte slutförts, och löfte är i väntan på uppfyllande.
  • uppfylld - Åtgärden är klar och löften uppfylls med ett värde . Detta är analogt med att returnera ett värde från en synkron funktion.
  • avvisad - Ett fel har inträffat under operationen, och löfte avvisas med anledning . Detta är analogt med att kasta ett fel i en synkronfunktion.

Ett löfte sägs vara avgjort (eller löst ) när det antingen uppfylls eller förkastas. När ett löfte är avgjort blir det oföränderligt och dess tillstånd kan inte förändras. then och catch för ett löfte kan användas för att bifoga återuppringningar som körs när det är avgjort. Dessa återuppringningar åberopas med uppfyllande respektive avvisningsskäl.

Löfte flödesschema

Exempel

const promise = new Promise((resolve, reject) => {
    // Perform some work (possibly asynchronous)
    // ...

    if (/* Work has successfully finished and produced "value" */) {
        resolve(value);
    } else {
        // Something went wrong because of "reason"
        // The reason is traditionally an Error object, although
        // this is not required or enforced.
        let reason = new Error(message);
        reject(reason);

        // Throwing an error also rejects the promise.
        throw reason;
    }
});

then och catch kan användas för att bifoga uppfyllande och avvisande återuppringningar:

promise.then(value => {
    // Work has completed successfully,
    // promise has been fulfilled with "value"
}).catch(reason => {
    // Something went wrong,
    // promise has been rejected with "reason"
});

Obs: Att ringa promise.then(...) och promise.catch(...) på samma löfte kan leda till ett Uncaught exception in Promise om ett fel inträffar, antingen vid genomförandet av löfte eller i en av återuppringningarna, så det föredragna sättet skulle vara att fästa nästa lyssnare på det löfte som returnerades av den föregående then / catch .

Alternativt kan båda återuppringningarna bifogas i ett enda samtal till then :

promise.then(onFulfilled, onRejected);

Om du kopplar återuppringningar till ett löfte som redan har fastställts kommer de omedelbart att placeras i mikrotaskkön , och de kommer att åberopas "så snart som möjligt" (dvs. omedelbart efter det nuvarande exekverande skriptet). Det är inte nödvändigt att kontrollera löftets tillstånd innan du kopplar återuppringningar, till skillnad från många andra händelsemitterande implementationer.


Live-demo

Fördröjningsfunktionssamtal

setTimeout() kallar en funktion eller utvärderar ett uttryck efter ett specificerat antal millisekunder. Det är också ett trivialt sätt att uppnå en asynkron operation.

I det här exemplet löser man wait funktionen löften efter den tid som anges som första argument:

function wait(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));  
}

wait(5000).then(() => { 
    console.log('5 seconds have passed...');
});

Väntar på flera samtidiga löften

Den statiska metoden Promise.all() accepterar en iterbar (t.ex. en Array ) av löften och returnerar ett nytt löfte, som löses när alla löften i det iterable har lösts, eller avvisar om åtminstone ett av löftena i det iterable har avvisat.

// wait "millis" ms, then resolve with "value"
function resolve(value, milliseconds) {
    return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}

// wait "millis" ms, then reject with "reason"
function reject(reason, milliseconds) {
    return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    resolve(3, 7000)    
]).then(values => console.log(values)); // outputs "[1, 2, 3]" after 7 seconds.

Promise.all([
    resolve(1, 5000),
    reject('Error!', 6000),
    resolve(2, 7000)
]).then(values => console.log(values)) // does not output anything
.catch(reason => console.log(reason)); // outputs "Error!" after 6 seconds.

Värden som inte är löfte i det iterable "lovas" .

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    { hello: 3 }
])
.then(values => console.log(values)); // outputs "[1, 2, { hello: 3 }]" after 6 seconds

Destruktureringsuppdrag kan hjälpa till att hämta resultat från flera löften.

Promise.all([
    resolve(1, 5000),
    resolve(2, 6000),
    resolve(3, 7000)
])
.then(([result1, result2, result3]) => {
    console.log(result1);
    console.log(result2);
    console.log(result3);
});

Väntar på det första av flera samtidiga löften

Den statiska metoden Promise.race() accepterar en iterable of Promises och returnerar ett nytt lovande som löser eller avvisar så snart det första av löften i iterable har lösts eller avvisats.

// wait "milliseconds" milliseconds, then resolve with "value"
function resolve(value, milliseconds) {
    return new Promise(resolve => setTimeout(() => resolve(value), milliseconds));
}

// wait "milliseconds" milliseconds, then reject with "reason"
function reject(reason, milliseconds) {
    return new Promise((_, reject) => setTimeout(() => reject(reason), milliseconds));
}

Promise.race([
    resolve(1, 5000),
    resolve(2, 3000),
    resolve(3, 1000)
])
.then(value => console.log(value)); // outputs "3" after 1 second.


Promise.race([
    reject(new Error('bad things!'), 1000),
    resolve(2, 2000)
])
.then(value => console.log(value)) // does not output anything
.catch(error => console.log(error.message)); // outputs "bad things!" after 1 second

"Promisifying" -värden

Den statiska metoden Promise.resolve kan användas för att förpacka värden till löften.

let resolved = Promise.resolve(2);
resolved.then(value => {
    // immediately invoked
    // value === 2
});

Om value redan är ett löfte omarbetar Promise.resolve helt enkelt det.

let one = new Promise(resolve => setTimeout(() => resolve(2), 1000));
let two = Promise.resolve(one);
two.then(value => {
    // 1 second has passed
    // value === 2
});

I själva verket kan value vara vilket som helst "dåligt" (objekt som definierar en then metod som fungerar tillräckligt som ett spec-kompatibelt löfte). Detta tillåter Promise.resolve att konvertera otillförlitliga tredje part-objekt till pålitliga första-partslöften.

let resolved = Promise.resolve({
    then(onResolved) {
        onResolved(2);
    }
});
resolved.then(value => {
    // immediately invoked
    // value === 2
});

Den statiska metoden Promise.reject returnerar ett löfte som omedelbart avvisar med det angivna reason .

let rejected = Promise.reject("Oops!");
rejected.catch(reason => {
    // immediately invoked
    // reason === "Oops!"
});

"Promisifying" -funktioner med återuppringningar

Med tanke på en funktion som accepterar en återuppringning i Node-stil,

fooFn(options, function callback(err, result) { ... });

Du kan lova det (konvertera det till en löfte-baserad funktion) så här:

function promiseFooFn(options) {
    return new Promise((resolve, reject) =>
        fooFn(options, (err, result) =>
            // If there's an error, reject; otherwise resolve
            err ? reject(err) : resolve(result)
        )
    );
}

Denna funktion kan sedan användas på följande sätt:

promiseFooFn(options).then(result => {
    // success!
}).catch(err => {
    // error!
});

På ett mer generiskt sätt så här kan du lova en given återuppringningsstil:

function promisify(func) {
    return function(...args) {
        return new Promise((resolve, reject) => {
            func(...args, (err, result) => err ? reject(err) : resolve(result));
        });
    }
}

Detta kan användas så här:

const fs = require('fs');
const promisedStat = promisify(fs.stat.bind(fs));

promisedStat('/foo/bar')
    .then(stat => console.log('STATE', stat))
    .catch(err => console.log('ERROR', err));

Felhantering

Fel som kastas från löften hanteras av den andra parametern ( reject ) som skickas till then eller av hanteraren som skickas för att catch :

throwErrorAsync()
  .then(null, error => { /* handle error here */ });
// or
throwErrorAsync()
  .catch(error => { /* handle error here */ });

kedja

Om du har en löftskedja kommer ett fel att resolve hanterare att hoppa över:

throwErrorAsync()
  .then(() => { /* never called */ })
  .catch(error => { /* handle error here */ });

Detsamma gäller för dina then funktioner. Om en resolve handler kastar ett undantag sedan nästa reject hanterare kommer att åberopas:

doSomethingAsync()
  .then(result => { throwErrorSync(); })
  .then(() => { /* never called */ })
  .catch(error => { /* handle error from throwErrorSync() */ });

En felhanterare returnerar ett nytt löfte så att du kan fortsätta med en löftskedja. Löfte som returneras av felhanteraren löses med värdet som returneras av hanteraren:

throwErrorAsync()
  .catch(error => { /* handle error here */; return result; })
  .then(result => { /* handle result here */ });

Du kan låta ett fel kaskadera ner en löftskedja genom att kasta felet igen:

throwErrorAsync()
  .catch(error => {
      /* handle error from throwErrorAsync() */
      throw error;
  })
  .then(() => { /* will not be called if there's an error */ })
  .catch(error => { /* will get called with the same error */ });

Det är möjligt att kasta ett undantag som inte hanteras av löftet genom att linda throw uttalande i en setTimeout återuppringning:

new Promise((resolve, reject) => {
  setTimeout(() => { throw new Error(); });
});

Detta fungerar eftersom löften inte kan hantera undantag som kastas asynkront.

Obehandlade avslag

Ett fel ignoreras tyst om ett löfte inte har ett catch eller reject hanterare:

throwErrorAsync()
  .then(() => { /* will not be called */ });
// error silently ignored

Använd alltid ett catch att förhindra detta:

throwErrorAsync()
  .then(() => { /* will not be called */ })
  .catch(error => { /* handle error*/ });
// or
throwErrorAsync()
  .then(() => { /* will not be called */ }, error => { /* handle error*/ });

Alternativt, prenumerera på unhandledrejection händelsen för att fånga eventuella Ohanterad avvisade löften:

window.addEventListener('unhandledrejection', event => {});

Vissa löften kan hantera deras avslag senare än deras skapelsestid. Händelsen som rejectionhandled hanteras varje gång ett sådant löfte hanteras:

window.addEventListener('unhandledrejection', event => console.log('unhandled'));
window.addEventListener('rejectionhandled', event => console.log('handled'));
var p = Promise.reject('test');

setTimeout(() => p.catch(console.log), 1000);

// Will print 'unhandled', and after one second 'test' and 'handled'

event innehåller information om avslaget. event.reason är event.reason och event.promise är det event.promise som orsakade händelsen.

I Nodejs kallas rejectionhandled och unhandledrejection händelserhändelser rejectionHandled och unhandledRejection vid process respektive och har en annan signatur:

process.on('rejectionHandled', (reason, promise) => {});
process.on('unhandledRejection', (reason, promise) => {});

reason är felobjektet och promise är en hänvisning till löfteobjektet som fick händelsen att skjutas.

Användning av dessa unhandledrejection och rejectionhandled händelser bör övervägas för endast felsökning. Vanligtvis bör alla löften hantera deras avslag.

OBS: För närvarande bara Chrome 49+ och Node.js support unhandledrejection och rejectionhandled händelser.

förbehåll

Kedja med fulfill och reject

Funktionen then(fulfill, reject) (med båda parametrarna inte null ) har unikt och komplext beteende och bör inte användas om du inte vet exakt hur det fungerar.

Funktionen fungerar som förväntat om den ges null för en av ingångarna:

// the following calls are equivalent
promise.then(fulfill, null) 
promise.then(fulfill)

// the following calls are also equivalent
promise.then(null, reject) 
promise.catch(reject)

Det antar emellertid unikt beteende när båda ingångar ges:

// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.then(fulfill).catch(reject)

// the following calls are not equivalent!
promise.then(fulfill, reject)
promise.catch(reject).then(fulfill)

Funktionen then(fulfill, reject) ser ut som om det är en genväg för then(fulfill).catch(reject) , men det är det inte och kommer att orsaka problem om de används omväxlande. Ett sådant problem är att den reject hanteraren inte hanterar fel från fulfill . Här är vad som kommer att hända:

Promise.resolve() // previous promise is fulfilled
    .then(() => { throw new Error(); }, // error in the fulfill handler
        error => { /* this is not called! */ });

Ovanstående kod kommer att resultera i ett avvisat löfte eftersom felet sprids. Jämför den med följande kod, vilket resulterar i ett uppfyllt löfte:

Promise.resolve() // previous promise is fulfilled
    .then(() => { throw new Error(); }) // error in the fulfill handler
    .catch(error => { /* handle error */ });

Ett liknande problem existerar när man då använder then(fulfill, reject) utbytbart med catch(reject).then(fulfill) , förutom med att sprida uppfyllda löften istället för avvisade löften.

Synkront kasta från funktion som borde ge ett löfte

Föreställ dig en sådan funktion:

function foo(arg) {
  if (arg === 'unexepectedValue') {
    throw new Error('UnexpectedValue')
  }

  return new Promise(resolve => 
    setTimeout(() => resolve(arg), 1000)
  )
}

Om en sådan funktion används i mitten av en löftskedja är det uppenbarligen inga problem:

makeSomethingAsync().
  .then(() => foo('unexpectedValue'))
  .catch(err => console.log(err)) // <-- Error: UnexpectedValue will be caught here

Men om samma funktion kallas utanför en löftskedja, kommer felet inte att hanteras av det och kommer att kastas till applikationen:

foo('unexpectedValue') // <-- error will be thrown, so the application will crash
  .then(makeSomethingAsync) // <-- will not run
  .catch(err => console.log(err)) // <-- will not catch

Det finns två möjliga lösningar:

Returnera ett avvisat löfte med felet

Gör så här istället för att kasta:

function foo(arg) {
  if (arg === 'unexepectedValue') {
    return Promise.reject(new Error('UnexpectedValue'))
  }

  return new Promise(resolve => 
    setTimeout(() => resolve(arg), 1000)
  )
}

Förpacka din funktion i en löfte kedja

Ditt throw kommer att fångas ordentligt när det redan finns i en löftskedja:

function foo(arg) {
  return Promise.resolve()
    .then(() => {
      if (arg === 'unexepectedValue') {
        throw new Error('UnexpectedValue')
      }

      return new Promise(resolve => 
        setTimeout(() => resolve(arg), 1000)
      )
    })
}

Avstämma synkrona och asynkrona operationer

I vissa fall kanske du vill linda in en synkron operation i ett löfte om att förhindra upprepning i kodgrenar. Ta detta exempel:

if (result) { // if we already have a result
  processResult(result); // process it
} else {
  fetchResult().then(processResult);
}

De synkrona och asynkrona grenarna i koden ovan kan förenas genom att den synkrona operationen redundant lindas in i ett löfte:

var fetch = result
  ? Promise.resolve(result)
  : fetchResult();

fetch.then(processResult);

När cachar resultatet av ett asynkront samtal är det att föredra att cache löftet snarare än själva resultatet. Detta säkerställer att endast en asynkron operation krävs för att lösa flera parallella förfrågningar.

Försiktighet bör iakttas att ogiltiga cachedvärden ogiltigförklaras när felförhållanden uppstår.

// A resource that is not expected to change frequently
var planets = 'http://swapi.co/api/planets/';
// The cached promise, or null
var cachedPromise;

function fetchResult() {
    if (!cachedPromise) {
        cachedPromise = fetch(planets)
            .catch(function (e) {
                // Invalidate the current result to retry on the next fetch
                cachedPromise = null;
                // re-raise the error to propagate it to callers
                throw e;
            });
    }
    return cachedPromise;
}

Minska en grupp till länkade löften

Detta designmönster är användbart för att generera en sekvens av asynkrona åtgärder från en lista över element.

Det finns två varianter:

  • den "då" reduktionen, som bygger en kedja som fortsätter så länge kedjan upplever framgång.
  • "fångst" -minskningen, som bygger en kedja som fortsätter så länge kedjan upplever fel.

Den "då" minskningen

Denna variant av mönstret bygger en .then() -kedja och kan användas för att kedja animationer eller göra en sekvens av beroende HTTP-förfrågningar.

[1, 3, 5, 7, 9].reduce((seq, n) => {
    return seq.then(() => {
        console.log(n);
        return new Promise(res => setTimeout(res, 1000));
    });
}, Promise.resolve()).then(
    () => console.log('done'),
    (e) => console.log(e)
);
// will log 1, 3, 5, 7, 9, 'done' in 1s intervals

Förklaring:

  1. Vi kallar .reduce() på en källarray och tillhandahåller Promise.resolve() som ett initialvärde.
  2. Varje reducerat element lägger till ett .then() till det initiala värdet.
  3. reduce() : s produkt kommer att vara Promise.resolve (). sedan (...). sedan (...).
  4. Vi lägger manuellt till en .then(successHandler, errorHandler) efter reduceringen för att utföra successHandler när alla tidigare steg har lösts. Om något steg skulle misslyckas, skulle errorHandler köra.

Obs: "Då" -reduktionen är en sekventiell motsvarighet till Promise.all() .

"Fångst" -minskningen

Denna variant av mönstret bygger en .catch() -kedja och kan användas för att sekventiellt undersöka en uppsättning webbserver för någon speglad resurs tills en fungerande server hittas.

var working_resource = 5; // one of the values from the source array
[1, 3, 5, 7, 9].reduce((seq, n) => {
    return seq.catch(() => {
        console.log(n);
        if(n === working_resource) { // 5 is working
            return new Promise((resolve, reject) => setTimeout(() => resolve(n), 1000));
        } else { // all other values are not working
            return new Promise((resolve, reject) => setTimeout(reject, 1000));
        }
    });
}, Promise.reject()).then(
    (n) => console.log('success at: ' + n),
    () => console.log('total failure')
);
// will log 1, 3, 5, 'success at 5' at 1s intervals

Förklaring:

  1. Vi kallar .reduce() på en källarray och tillhandahåller Promise.reject() som ett initialvärde.
  2. Varje element som reduceras lägger till en .catch() till det initiala värdet.
  3. reduce() : s produkt kommer att vara Promise.reject().catch(...).catch(...) .
  4. Vi lägger manuellt till .then(successHandler, errorHandler) efter reduceringen, för att utföra successHandler när något av de tidigare stegen har lösts. Om alla steg skulle misslyckas, skulle errorHandler utföra.

Obs: "Fångst" -minskningen är en sekventiell motsvarighet till Promise.any() (implementerad i bluebird.js , men för närvarande inte i det egna ECMAScript).

för alla med löften

Det är möjligt att effektivt tillämpa en funktion ( cb ) som returnerar ett löfte till varje element i en matris, där varje element väntar på att bearbetas tills det föregående elementet bearbetas.

function promiseForEach(arr, cb) {
  var i = 0;

  var nextPromise = function () {
    if (i >= arr.length) {
      // Processing finished.
      return;
    }

    // Process next function. Wrap in `Promise.resolve` in case
    // the function does not return a promise
    var newPromise = Promise.resolve(cb(arr[i], i));
    i++;
    // Chain to finish processing.
    return newPromise.then(nextPromise);
  };

  // Kick off the chain.
  return Promise.resolve().then(nextPromise);
};

Detta kan vara till hjälp om du behöver bearbeta tusentals artiklar på en gång. Att använda en vanlig for loop för att skapa löften skapar dem alla på en gång och tar upp en betydande mängd RAM.

Utför rensning med äntligen ()

Det finns för närvarande ett förslag (ännu inte en del av ECMAScript-standarden) att lägga till ett finally återuppringning till löften som kommer att genomföras oavsett om löften uppfylls eller förkastas. Semantiskt, är detta liknar det finally klausul i try blocket .

Du brukar använda den här funktionen för sanering:

var loadingData = true;

fetch('/data')
    .then(result => processData(result.data))
    .catch(error => console.error(error))
    .finally(() => {
        loadingData = false;
    });

Det är viktigt att notera att den finally återuppringningen inte påverkar löftets tillstånd. Det spelar ingen roll vilket värde det returnerar, löfteet förblir i det uppfyllda / avvisade tillståndet som det hade tidigare. Så i exemplet ovan kommer löftet att lösas med returvärdet för processData(result.data) även om den finally återuppringningen returneras undefined .

När standardiseringsprocessen fortfarande pågår stöder ditt implementering av löften sannolikt inte finally återuppringningar ur ramen. För synkrona återuppringningar kan du dock lägga till den här funktionen med en polyfyll:

if (!Promise.prototype.finally) {
    Promise.prototype.finally = function(callback) {
        return this.then(result => {
            callback();
            return result;
        }, error => {
            callback();
            throw error;
        });
    };
}

Asynkron API-begäran

Detta är ett exempel på ett enkelt GET API-samtal inslaget i ett löfte om att dra fördel av dess asynkrona funktionalitet.

var get = function(path) {
  return new Promise(function(resolve, reject) {
    let request = new XMLHttpRequest();
    request.open('GET', path);
    request.onload = resolve;
    request.onerror = reject;
    request.send();
  });
};

Mer robust felhantering kan göras med följande onload och onerror funktioner.

request.onload = function() {
  if (this.status >= 200 && this.status < 300) {
    if(request.response) {
      // Assuming a successful call returns JSON
      resolve(JSON.parse(request.response));
    } else {
      resolve();
  } else {
    reject({
      'status': this.status,
      'message': request.statusText
    });
  }
};

request.onerror = function() {
  reject({
    'status': this.status,
    'message': request.statusText
  });
};

Använda ES2017 async / invänta

Samma exempel ovan, Image loading , kan skrivas med hjälp av async-funktioner . Detta gör det också möjligt att använda den vanliga try/catch metoden för undantagshantering.

Obs! Från och med april 2017 stöder de aktuella utgåvorna för alla webbläsare men Internet Explorer stöder async-funktioner .

function loadImage(url) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.addEventListener('load', () => resolve(img));
        img.addEventListener('error', () => {
            reject(new Error(`Failed to load ${url}`));
        });
        img.src = url;
    });
}

(async () => {

    // load /image.png and append to #image-holder, otherwise throw error
    try {
        let img = await loadImage('http://example.com/image.png');
        document.getElementById('image-holder').appendChild(img);
    }
    catch (error) {
        console.error(error);
    }

})();


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow